ポートフォリをとして作ったRuby on RailsアプリをDockerコンテナ化し本番環境をAWSで構築するまでの道のりです。
ポートフォリオ自体はこちらとなります。
[【ポートフォリオ】転職活動時に作成したポートフォリオの概要(テッ◯キャンプ)]
(https://qiita.com/sho_U/items/058e590325ee6833abb0)
かなり苦しめられたので、どなたかのお役に立てれば。
タイトル | |
---|---|
1 | ローカル環境のRailsアプリをDockerコンテナ化 |
2 | AWSにVPCを作成する。パブリックサブネットを作成する |
3 | プライベートサブネットを作成する |
4 | EC2インスタンスを作成する |
5 | RDSを作成する |
6 | DockerコンテナをAWSにアップロードする |
#DockerコンテナをAWSにアップロードします。
この項目では、かなり苦しめられました。ngixやpuma、RDSなど接続しなくてはいけないものが多々あり、また、AWS内にコンテナを構築することにより今、自分がどこにいるのか、よくわからなくなる状態に陥ることがありました。
この記事通りに、行ってもうまくいかないかもしれませんが、少しでもどなたかのお力になれればと思います。
自分はできれば、再びあのような思いをしたく無いので忘れないうちに記事として残しておきました。
作成したAWSインスタンスにローカルdockerコンテナをアップロードしていきます。
##コンテナ内での環境変数を設定します。
現状、database.ymlを確認すると
username: root
password: password
host: db
このように、セキュアな情報がハードコーディングされています。
このままではgithubのコードから漏洩する危険があるので、本番環境のコンテナ内で環境変数を用いてセキュアな情報を設定します。
環境変数については、参考までに下記をご覧下さい。
[環境変数について]
(https://qiita.com/sho_U/items/cd5fc4d4d76b65b92d23)
環境変数を利用するために、dotenv-railsというgemをインストールします。
Gemfileに以下を追記します。
gem 'dotenv-rails'
dotenv-railsをインストールすることにより、「.env」ファイルに記載された環境変数をdockerコンテナ内で、下記のような記述で取り出せる様になります。
ENV['DATABASE_PASSWORD']
また、.envファイルをgithubに上げてしまうと元も子も無いので、gitignoreに追記します。
.env
.envを下記の様に記載してアプリ直下に配置します。
DB_USERNAME=root
DB_PASSWORD=gakjadfmoaeur
DB_HOST=fito2-db-instance.〇〇〇〇〇〇.ap-northeast-1.rds.amazonaws.com
DB_DATABASE=fitO2_db
DB_HOSTはRDSのエンドポイントです。
AWSのRDSダッシュボードのデーターベースをクリックし、一覧から該当のRDSを選択すると確認できます。
##database.ymlの修正
database.ymlに下記を追加して、本番環境は環境変数から値を読み込むようにします。
production:
<<: *default
database: <%= ENV['DB_DATABASE'] %>
adapter: mysql2
encoding: utf8mb4
charset: utf8mb4
collation: utf8mb4_general_ci
host: <%= ENV['DB_HOST'] %>
username: <%= ENV['DB_USERNAME'] %>
password: <%= ENV['DB_PASSWORD'] %>
##nginx.confの修正
以下の部分を本番用に修正します。
server {
listen 80;
# =========ローカルと本番切り替え===========
server_name 固定IP;
# server_name localhost;
# ======================================
##docker-compose.ymlの修正
version: '3'
services:
app:
build:
context: .
# =========ローカルと本番切り替え===========
command: bundle exec puma -C config/puma.rb -e production
# command: bundle exec puma -C config/puma.rb
# ======================================
volumes:
- .:/fitO2
- public-data:/fitO2/public
- tmp-data:/fitO2/tmp
- log-data:/fitO2/log
networks:
- fitO2-network
# =========ローカルと本番切り替え===========
# depends_on:
# - db
# db:
# image: mysql:5.7
# environment:
# MYSQL_ROOT_PASSWORD: password
# MYSQL_USER: user
# MYSQL_PASSWORD: password
# MYSQL_DATABASE: fitO2_development
# volumes:
# - db-data:/var/lib/mysql
# networks:
# - fitO2-network
# ======================================
web:
build:
context: ./nginx_docker
volumes:
- public-data:/fitO2/public
- tmp-data:/fitO2/tmp
ports:
- 80:80
depends_on:
- app
networks:
- fitO2-network
volumes:
public-data:
tmp-data:
log-data:
db-data:
networks:
fitO2-network:
external: true
変更点
・dbコンテナは本番環境ではRDSを使用するので不要のため、コメントアウト
(appコンテナのdepend onもまとめてコメントアウトします)
・command のrails s に -e production を追記して、本番環境でサーバー立ち上げるようにした。
##AWSインスタンス上にdockerコンテナを構築する。
今一度、AWSインスタンス上にdockerコンテナを構築するまでの流れを整理します。
今、現状ローカルでは、下記のようにfitO2というファイルを元に、下記の様なdockerコンテナをbuildできる状態でした。
そして、fitO2というファイルを書き換えて、以下の様なコンテナが作成されるように修正しました。(DBコンテナ削除)
その、fitO2をgithubにpushします。そして、AWS側からclone(2回目以降はpull)します。
cloneしたfitO2を元に、AWS内でbuildしてコンテナを構築し、AWS内に作成しているRDSと接続します。
通信の流れはオレンジの矢印となります。
##githubへプッシュ
まずは、修正したファイルをコミットしてgithubへpushします。
##AWSにdockerをインストール
ssh接続でAWSにログインし、dockerをインストールします。
sudo yum install -y docker
//インストール
sudo service docker start
//docker起動
sudo usermod -G docker ec2-user
//ec2-userに権限付与
exit
//ログアウト
//再度sshでログイン
docker info
下記の様な表示がされたらオッケーです。
Client:
Debug Mode: false
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 19.03.13-ce
sudo chkconfig docker on
//EC2起動時にDockerを自動で立ち上げる
docker-composeをインストールします。
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
docker-compose -v
docker-compose version 1.24.0, build 0aa59064
//上記の様にバージョンが表示されたら成功
//Permission denied となる場合は
sudo chmod +x /usr/local/bin/docker-compose
//でdocker-composeへ実行権限を付与したあとにもう一度 docker-compose -v を実行するとversionが表示されます。
gitをインストールします。
sudo yum install -y git
秘密鍵を作成します。(質問は全てエンター)
ssh-keygen -t rsa -b 4096
作成した秘密鍵を表示し、コピーします。
cat ~/.ssh/id_rsa.pub
https://github.com/settings/keys
こちらにアクセスします。
titleを適宜入力し、keyのところに先ほどコピーした文字列を貼り付けます。
(ssh-rsa~から含めます)
ssh -T git@github.com
上記を打ち込んで、途中yesと入力し、下記の様に表示されればAWSとgithubの認証が成立しました。
Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.
以後、AWSインスタンス側から自身のgithubに対し、pull等ができる様になります。
githubからcloneします。(URLはリポジトリを表示したときのURL)
cd /
//ルート直下に移動します。homeディレクトリでコンテナを展開すると、pumaとnginxの連携でエラーが出る場合がありますl。puma.sockの読み取りエラー
sudo git clone https://github.com/〇〇〇〇〇〇/〇〇〇〇〇〇
ls
//lsと打って、ディレクトリがあるか確認する。
今、gitignoreに記載したファイル(.env master.key)は含まれていません。そこで、ssh通信を用いてローカルからAWSに直接ファイルを転送します。
exit
//一旦ログアウトして、ローカルのfitO2ファイルに移動
sudo scp -i ~/.ssh/fitO2_key.pem .env ec2-user@固定IP:/home/ec2-user/
sudo scp -i ~/.ssh/fitO2_key.pem config/master.key ec2user@固定IP:/home/ec2-user
//scpコマンドを用いて、AWSに.envを転送します。 .env のように転送したファイルが表示されたらオッケー。
//権限の関係で一旦、ホームディレクトリに転送します。
再度、ログイン。
cd
ls -a
ホームディレクトリに移動して.envとmaster.keyが存在していたら問題ない。
.envとmaster.keyを移動させる。
sudo mv .env /fitO2
sudo mv master.key /fitO2/config
念のため移動してるか確認
ls -a /fitO2/
ls -a /fitO2/config
##コンテナの起動
cd /fitO2
docker-compose build
//コンテナを作成します。
(Permition deniedになった場合は、sudo chmod 777 /usr/local/bin/docker-compose
を実行します。)
docker network create fitO2-network
//ネットワークを作成します。
docker-compose run app rails assets:precompile RAILS_ENV=production
//プリコンパイルを実施
docker-compose up
//コンテナを起動します。
下記のように表示されていれば問題なく起動しています。
Creating fito2_app_1 ... done
Creating fito2_web_1 ... done
Attaching to fito2_app_1, fito2_web_1
app_1 | Puma starting in single mode...
app_1 | * Version 3.12.6 (ruby 2.5.1-p57), codename: Llamas in Pajamas
app_1 | * Min threads: 5, max threads: 5
app_1 | * Environment: production
app_1 | * Listening on tcp://0.0.0.0:3000
app_1 | * Listening on unix:///fitO2/tmp/sockets/puma.sock
app_1 | Use Ctrl-C to stop
別タブを開いて、AWSにログインします。
###データベースの作成
docker-compose exec app rails db:create db:migrate RAILS_ENV=production
docker-compose exec app rails db:seed RAILS_ENV=production
//(必要に応じて)
以上で、http://固定IPにアクセスした場合、正しく表示されるはずです。
##RDSのデーターベース確認方法
#dockerコンテナにログインし、mysqlを起動させます。
docker ps
//コンテナIDを調べます。
NAMESがfito2_app_1の方のCONTAINER IDをコピーします。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5ec64f0ea76 fito2_web "/bin/sh -c '/usr/sb…" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp fito2_web_1
442b9ddb3a20 fito2_app "bundle exec puma -C…" 5 minutes ago Up 5 minutes fito2_app_1
コンテナにログインします
docker exec -it 442b9ddb3a20 bash
mysqlを起動させます。
service mysql start
mysql -u root -h RDSのエンドポイント -p
//パスワードを入力してログイン
セキュリティーグループで制限んしているので、作成したEC2コンテナからしかアクセスできません。
ローカルから試してみてください。
以上となります。
###参考
EC2上でRailsアプリケーションにDockerを導入する(Rails、Nginx、RDS)
[開発環境において既存のRailsアプリにDockerを導入する方法(Rails、nginx、mysql)]
(https://qiita.com/Yusuke_Hoirta/items/18dae771163a02a53a37)
[無料!かつ最短?で Ruby on Rails on Docker on AWS のアプリを公開するぞ。]
(https://qiita.com/at-946/items/1e8acea19cc0b9f31b98)
【画像付きで丁寧に解説】AWS(EC2)にRailsアプリをイチから上げる方法【その1〜ネットワーク,RDS環境設定編〜】
Nginx + Rails (Puma) on Docker のいくつかの実用パターン
[Docker + Rails + Puma + Nginx + MySQL]
(https://qiita.com/eighty8/items/0288ab9c127ddb683315)