CodeBuildのCacheをsymlinkで使うとうまく動かない


CodeBuildじゃなくてDockerの話かもしれませんが。

CodeBuildにcacheが実装され、趣味コードのビルドとかには非常に便利になりました。

https://aws.amazon.com/jp/blogs/devops/how-to-enable-caching-for-aws-codebuild/

でも死ぬほどハマったのでメモ。


## 結論
キャッシュを使うのにsymlinkはだめ、コピーして持って来る。


## 検証
下記のような `buildspec.yaml` を用意します。

```yaml
version: 0.2 

phases:
  install:
    commands:
      - mkdir -p ~/.carton_cache
      - mkdir -p ~/.npm_cache
      - if [ ! -e "$CODEBUILD_SRC_DIR/local" ];              then ln -s /root/.carton_cache $CODEBUILD_SRC_DIR/local ;             fi  
      - if [ ! -e "$CODEBUILD_SRC_DIR/react/node_modules" ]; then ln -s /root/.npm_cache    $CODEBUILD_SRC_DIR/react/node_modules; fi

  build:
    commands:
      - /opt/perl-5.22/bin/perl /opt/perl-5.22/bin/carton install
      - /opt/perl-5.22/bin/perl /opt/perl-5.22/bin/carton exec /opt/perl-5.22/bin/perl t/Util.pm
      - /opt/perl-5.22/bin/perl /opt/perl-5.22/bin/carton exec /opt/perl-5.22/bin/prove
      - cd react
      - npm install
      - webpack -p
      - cd ..
      - zip -r /tmp/app.zip . 

artifacts:
  files:
    - /tmp/app.zip
  discard-paths: yes

cache:
  paths:
    - '/root/.carton_cache/**/*'
    - '/root/.npm_cache/**/*'

```

今回追加されたのは `cache` セクションで、ビルド後に `cache` セクションで指定されたファイルをキャッシュします。

`CODEBUILD_SRC_DIR` には `/codebuild/output/src029595350` のような一時ディレクトリが入るのでsymlinkを張って固定ディレクトリをキャッシュするようにします。


で、こんな感じのエラーが出る。

```
[Container] 2017/12/07 02:50:19 Running command webpack -p 
module.js:544 
throw err; 
^  

Error: Cannot find module 'async' 
at Function.Module._resolveFilename (module.js:542:15) 
at Function.Module._load (module.js:472:25) 
at Module.require (module.js:585:17) 
at require (internal/module.js:11:18) 
at Object.<anonymous> (/root/.npm_cache/webpack/lib/Compilation.js:7:18) 
at Module._compile (module.js:641:30) 
at Object.Module._extensions..js (module.js:652:10) 
at Module.load (module.js:560:32) 
at tryModuleLoad (module.js:503:12) 
at Function.Module._load (module.js:495:3)  

[Container] 2017/12/07 02:50:19 Command did not exit successfully webpack -p exit status 1 
[Container] 2017/12/07 02:50:19 Phase complete: BUILD Success: false 
[Container] 2017/12/07 02:50:19 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: webpack -p. 
Reason: exit status 1
```

で、散々悩んだんですがsymlinkがダメだった。

symlinkではなく、実行前にキャッシュのディレクトリからコピーして来る、実行後にキャッシュのディレクトリへコピーする、をやりましょう。

```yaml
  install:
    commands:
      - mkdir -p ~/.carton_cache
      - mkdir -p ~/.npm_cache
      - cp -r ~/.carton_cache $CODEBUILD_SRC_DIR/local
      - cp -r ~/.npm_cache    $CODEBUILD_SRC_DIR/react/node_modules
```

```yaml
  build:
    commands:
      - rm -Rf ~/.carton_cache
      - rm -Rf ~/.npm_cache
      - cp -r $CODEBUILD_SRC_DIR/local              ~/.carton_cache
      - cp -r $CODEBUILD_SRC_DIR/react/node_modules ~/.npm_cache
```


## コピペ用設定ファイル

```
version: 0.2

#env:
#  variables:
#    aa: 1

phases:
  install:
    commands:
      - mkdir -p ~/.carton_cache
      - mkdir -p ~/.npm_cache
      - cp -r ~/.carton_cache $CODEBUILD_SRC_DIR/local
      - cp -r ~/.npm_cache    $CODEBUILD_SRC_DIR/react/node_modules

  build:
    commands:
   	  # インストールとかテストとかコード生成とかをここに追加
      - rm -Rf ~/.carton_cache
      - rm -Rf ~/.npm_cache
      - cp -r $CODEBUILD_SRC_DIR/local              ~/.carton_cache
      - cp -r $CODEBUILD_SRC_DIR/react/node_modules ~/.npm_cache

artifacts:
  files:
    - /tmp/mogemoge.zip
  discard-paths: yes

cache:
  paths:
    - '/root/.carton_cache/**/*'
    - '/root/.npm_cache/**/*'
```