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

# はじめに

前回の記事
>[EC2でのDocker環境の構築(ArgumentError: Missing 'secret_key_base'、Mysql2::Error::ConnectionError: Access denied for user 'root'@'172.18.0.4' (using password: NO)の解決法)](https://qiita.com/sc30gsw/items/434a51226020576cfecb)

で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を作成することができていますので、後は、それを起動してデプロイするだけです。

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

 # unicornは必須か？

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

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

```ruby:ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
```
このコマンドでサーバーを起動しました。

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

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

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

>
① [Unicornエラー（unicorn.pid not writable (ArgumentError)）](https://teratail.com/questions/148750)
② [【Capistrano,Unicorn】ArgumentError: directory for pid=/var/www/myapp/current/shared/tmp/pids/unicorn.pid not writableが書き込み権限の問題ではなかった](https://qiita.com/moai891/items/86668636f15b1723b758)
③ [unicorn.pid not writable (ArgumentError)でUnicornが起動できない](https://blog.nagatech.work/post/ruby/78)

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

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

```ruby:ターミナル(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と思いきや、開発環境の物も入るとエラーが出たので、以下を入力しました。

```ruby:ターミナル(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
```
エディタの方も記述を少し変えました。

```ruby: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
```

```ruby: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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/089b1231-2f65-ab70-d345-7af580aa982f.png)

# Webpacker::Manifest::MissingEntryError 

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

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

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

`rails s`などででてきた場合は以下の記事を参考にしてみてください。
こちらの記事では**Webpacker周辺のエラー解決の方法**を紹介しています。
>[[Rails6]Webpacker::Manifest::MissingEntryErrorの対処法4選](https://qiita.com/sc30gsw/items/7cdafe95323ef562814f)


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

## Dockerコンテナでアセットコンパイルの実行
```ruby:ターミナル(EC2)
[ec2-user@ip-XXX-XX-XX-XXX リポジトリ名]$ docker-compose run web rails assets:precompile RAILS_ENV=production
```

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

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

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


# 参考文献
[Docker + Rails5.2 + Unicorn + Nginx + capistranoで自動デプロイ](https://qiita.com/gyu_outputs/items/c960c903e7bc6f684a44)

[Rails6 開発時につまづきそうな webpacker, yarn 関係のエラーと解決方法](https://qiita.com/NaokiIshimura/items/8203f74f8dfd5f6b87a0)

[【Rails6】Webpacker::Manifest::MissingEntryErrorが出たときの対処法](https://qiita.com/masatwork/items/1b5d190cc76f5eeffbb7)