Dockerを使ってRails+Webpackerで環境構築しようと思ったら以下のようなエラーに遭遇した。
ERROR: Service 'webpacker' failed to build: COPY failed: stat /var/lib/docker/overlay2/7a5a91db824e62b94de842827e48bdea3dc9c4d2d36c17134fcf61c8bf8dfdc9/merged/opt/yarn-v1.13.0: no such file or directory
Dockerfile
FROM node:10 as node
FROM ruby:2.6.2
ENV LANG C.UTF-8
ENV YARN_VERSION 1.13.0
RUN apt-get update -qq && apt-get install -y build-essential graphviz libpq-dev
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
apt-get install nodejs
COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg
RUN gem install bundler
CMD ["/bin/sh", "-c", "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"]
全く同じ構成でも動く人と動かない人(自分)が存在して解決に時間がかかった。
原因
自分がDockerでの環境構築を始めたのが遅かったから。
もう少し具体的に言うと、Dockerを使い始めたのが遅かった為、指定したversionのyarnをコンテナ内にCopyできず、冒頭にあるようなエラーが発生していた。
ENV YARN_VERSION 1.13.0
という指定を、 COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
でしており、今回でいうと FROM node:10 as node
でpullしてきたベースのイメージから、yarnの1.13.0をコピーさせる命令を出しているが、そのVersionのyarnを扱ったnodeは自分のimageにはなく、pullしてきたnodeの中にもない(同じ構成で構築できた人は以前使ったyarn1.13.0が自分のimagesに存在しており、Dockerの仕組み上ローカルにベースイメージがあればそれを使い、もしなければDockerHubからpullする為、ローカルのimageを使って結果buildできた)為、そんなファイルやディレクトリはないと怒られていた。
解決策
copy時のVersion指定をワイルドカード(あるいは最新版などの指定nodeに存在するVersionを選ぶ。)
FROM node:10 as node
FROM ruby:2.6.2
ENV LANG C.UTF-8
##Yarnのバージョン指定は不要
RUN apt-get update -qq && apt-get install -y build-essential graphviz libpq-dev
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
apt-get install nodejs
COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn <== ここの[v$YARN_VERSION] で環境変数指定でCopyしようとしていた部分を[*]ワイルドカードにする。
COPY --from=node /usr/local/bin/node /usr/local/bin/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg
RUN gem install bundler
CMD ["/bin/sh", "-c", "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"]
これで、指定nodeの中から、使えるversionのyarnをCOPYしてbuildする事ができるようになる。
実際の業務などでは、そもそもDockerを使う理由としてLocalでの開発環境から開放されたいのに、Docker内のモジュールのバージョンが各自違うというのはアレなのでbuildしたものを全員で共有して開発するというやり方がよい。