はじめに
RailsアプリをDockerで環境を分けてbuildしようとしたときに詰まったことがありました。同じように詰まっている人の一助になればと思っています。環境
macOS Big Sur 11.6.6rails 6.1.6
Docker 20.10.7
docker-compose 1.29.2
原因
- 開発・本番ともにDocker環境で構築
- 開発・本番でシステム構成が異なるのでDockerfile、docker-composeの中身が違う
- 開発から本番に移行する際に、Dockerfile、docker-composeの中身を本番に合うように変えた
- 以降、開発環境でDockerが使えなくなった
解決
- 開発環境用のファイルと本番環境用のファイルをそれぞれ用意する(自分的に一番簡単な方法だった)
システム構成
開発環境(本番との違い: Nginxを使っていない、PostgreSQLのDockerイメージ使用)Dockerfile.dev
FROM ruby:2.7.6
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update -qq \
&& apt-get install -y build-essential libpq-dev nodejs yarn postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ENV PATH $PATH:/usr/local/src/bin
# コンテナー起動時に毎回実行されるスクリプトを追加
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# イメージ実行時に起動させる主プロセスを設定
CMD ["rails", "server", "-b", "0.0.0.0"]
docker-compose.dev.yml
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build:
context: .
dockerfile: Dockerfile.dev
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
tty: true
stdin_open: true
本番環境(開発との違い: NginxのDockerイメージを使用、かつ開発で使ったPostgreSQLのDockerイメージを使っていない→AWSのRDSを使用)
※scouterはアプリ名
Dockerfile
FROM ruby:2.7.6
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update -qq \
&& apt-get install -y build-essential libpq-dev nodejs yarn postgresql-client
WORKDIR /scouter
COPY Gemfile /scouter/Gemfile
COPY Gemfile.lock /scouter/Gemfile.lock
RUN gem install bundler
RUN bundle install
RUN bundle config set with production
RUN bundle config set without test development
RUN mkdir -p tmp/sockets
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
docker-compose.yml
version: '3'
services:
app:
build:
context: .
command: bundle exec puma -C config/puma.rb -e production
volumes:
- .:/scouter
- public-data:/scouter/public
- tmp-data:/scouter/tmp
- log-data:/scouter/log
networks:
- scouter-network
web:
build:
context: ./nginx_docker
volumes:
- public-data:/scouter/public
- tmp-data:/scouter/tmp
ports:
- 80:80
depends_on:
- app
networks:
- scouter-network
stdin_open: true
tty: true
volumes:
public-data:
tmp-data:
log-data:
db-data:
networks:
scouter-network:
external: true
ファイルの置き場所
本番用のDockerfile、docker-compose.ymlが置いてある同じディレクトリに開発用のDockerfile.dev、docker-compose.dev.ymlを配置した場合、docker-compose.dev.ymlは以下のようなパスで開発用のDockerfile.devを呼び出すようにする(開発用のファイルを違うディレクトリにした場合、それに合わせてパスを変える)。
docker-compose.dev.yml
web:
build:
context: .
dockerfile: Dockerfile.dev
DockerのBuild方法
開発環境
Dockerをビルドする
ターミナル
$ docker-compose -f docker-compose.dev.yml build
Dockerをアップする
ターミナル
$ docker-compose -f docker-compose.dev.yml up -d
本番環境
Dockerをビルドする(通常通り)
ターミナル
$ docker-compose build
Dockerをアップする(通常通り)
ターミナル
$ docker-compose up -d
警告
上記コマンドでビルドすると2つのファイルがマージされてビルドされてしまいます!
開発と環境で構成を完全に分けた場合はうまくビルドされません。
docker-compose -f docker-compose.yml -f docker-compose.dev.yml build
※記事内容で間違いなどあれば、ご指摘ください。
参考記事
https://techtechmedia.com/docker-compose-dev-prod/https://techracho.bpsinc.jp/gengen/2020_05_01/91520