😀

EC2 ✕ Docker・docker-composeによる手動デプロイ・アセットコンパイル

2020/12/30に公開

はじめに

前回の記事

EC2でのDocker環境の構築(ArgumentError: Missing 'secret_key_base'、Mysql2::Error::ConnectionError: Access denied for user 'root'@'172.18.0.4' (using password: NO)の解決法)

でEC2でのDockerの導入について解説しました。

今回はその続きで、EC2でDockerとdocker-composeを用いたEC2上でのDockerコンテナ起動とRailsアプリを手動デプロイしサーバーを起動するための方法やエラー解決などを解説していきます。

前提

① 開発環境でDockerおよびdocker-composeを導入していること

② EC2の初期設定(環境設定)でDockerとdocker-composeをインストールしていること

開発環境

Ruby 2.6.5
Bundler 2.1.4
Rails 6.0.0
MySQL 5.6.50
AWS EC2

EC2上でRailsアプリを起動する

前回まででEC2上でDocker内にDBを作成することができていますので、後は、それを起動してデプロイするだけです。

ただ、ここの起動で自分は結構手こずり8時間くらい起動できずに悶々としてました(笑)

unicornは必須か?

自分の場合EC2のデプロイではunicornが必須だと思っていたし、Dockerとunicornでサーバーを起動できている記事もちらほら見かけたので、それで行けると思っていました。

ただ、そこで沼にハマりました。
普通にDBができたのでターミナルで以下を実行。

ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

このコマンドでサーバーを起動しました。

すると以下の様なエラーが出ました。

ターミナル(EC2)
ArgumentError: directory for
pid=/var/www/app/tmp/pids/unicorn.pid not writable

最初は権限の問題かなと思ったり、app/tmp/pidのディレクトリが無いのかと思い以下記事を参考に試行錯誤しました。
以下の記事を参考に作業をしました。

Unicornエラー(unicorn.pid not writable (ArgumentError))
【Capistrano,Unicorn】ArgumentError: directory for pid=/var/www/myapp/current/shared/tmp/pids/unicorn.pid not writableが書き込み権限の問題ではなかった
unicorn.pid not writable (ArgumentError)でUnicornが起動できない

が、どれもうまく行かず振り出しに...

だとしたら他に原因は...と考えていたら、「そもそもコンテナ起動するから、わざわざunicornでサーバー起動しなくても良いのでは?」と思い、コンテナを起動。

ターミナル(EC2)
# コンテナ作成
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose build
# コンテナ内にDB作成
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:create RAILS_ENV=production
# コンテナ内でマイグレーションの実行
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:migrate RAILS_ENV=production
# コンテナを起動
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose up -d
# -dオプションを付けることでバックグラウンドで起動できる
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker ps -a
# statusがupになっているか確認

これでデプロイではず...とhttp://Elastic IP:3000/にアクセスすると、database_developmentがないと怒られました。

database_developmentの作成

自分の場合は特殊なのかどうかわかりませんが、RAILS_ENV=productionで本番環境のDBを作成したからOKと思いきや、開発環境の物も入るとエラーが出たので、以下を入力しました。

ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:create 
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails db:migrate

エディタの方も記述を少し変えました。

docker-compose.yml(変更前)
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 'password' 
    ports:
      - "4306:3306" #DockerコンテナとSequelpro接続の為に必要な設定

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
# volumes の部分を変更
    volumes:
      - .:/アプリ名
    ports:
      - "3000:3000"
    depends_on:
      - db
docker-compose.yml(変更後)
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 'password' 
    ports:
      - "4306:3306" #DockerコンテナとSequelpro接続の為に必要な設定

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
# volumes をアプリ名から変更
    volumes:
      - ./mysql:/var/lib/mysql
    ports:
      - "3000:3000"
    depends_on:
      - db

これで保存、更新し、ブラウザ表示すると、今度はまた違ったエラーが出ました。

1ffcbcf57f6384e2a905697ee4066865.png

Webpacker::Manifest::MissingEntryError

「お、エラーが変わったな!」と思い、解決に取り組むが、これが中々難しかった。

どういうエラーかというと「ブラウザがJavaScriptなどを読み込めていない」というエラーです。

そのために、何をするのかというと、ブラウザが読み込めるようにすればアセットコンパイルを行えば良いのですが、ちょっとした確認などが必要でして、、、それにハマりました。

rails sなどででてきた場合は以下の記事を参考にしてみてください。
こちらの記事ではWebpacker周辺のエラー解決の方法を紹介しています。

[Rails6]Webpacker::Manifest::MissingEntryErrorの対処法4選

ということで、アセットコンパイルを実行します

Dockerコンテナでアセットコンパイルの実行

ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails assets:precompile RAILS_ENV=production

コンテナ内でもアセットコンパイルを行い、コンテナを起動します。

ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose up

**http://Elastic IP:3000/**にアクセスすることができたら
成功です。

参考文献

Docker + Rails5.2 + Unicorn + Nginx + capistranoで自動デプロイ

Rails6 開発時につまづきそうな webpacker, yarn 関係のエラーと解決方法

【Rails6】Webpacker::Manifest::MissingEntryErrorが出たときの対処法

Discussion