個人的リマインド用
参考
Docker超入門講座 合併版 | ゼロから実践する4時間のフルコース
Dockerって何?
アプリを簡単に開発・デプロイできる仕組みのこと。
OS、ライブラリ、アプリケーションをひとまとめにして、配布できる。さらにテスト環境だけでなく、本番環境でも使える。
環境構築 for mac
今回必用なもの
iTerm2,VSCode,Docker,Gitそれぞれ動画に従いインストール
Dockerを使ってみよう
docker run hello-world
何が起こっているか
イメージからコンテナを作成し、起動させている。
イメージ: コンテナに必用なものを記載した雛形
コンテナ: Dockerの実行環境
クライアント(依頼主)がdocker runというコマンドをデーモンに対して伝える
↓
デーモンはバックグラウンドで起動していてクライアントの命令通りに、イメージやコンテナを操作するアプリケーションのこと
↓
今回、デーモンはhello worldという命令を受け取ったら、レジストリ(オンライン上で保存しておく場所)からhello worldのイメージをとってくる
↓
その後デーモンは、とってきたイメージをもとにコンテナを作成し、起動させて結果としてhello worldが表示される
アプリを実行・作成しよう
今回はRubyでWebサーバーを用意し、トップページにアクセスされたらhelloと返す
基本的な流れ
1.アプリコードとDockerfileを用意
2.そこからDockerのイメージを作成
3.イメージからコンテナを作成し起動
イメージを作る下準備
まずmain.rbというファイルを用意し、webサーバーを用意しhelloと表示するコードを書く(アプリケーションコード)
続いてDockerfile(イメージの雛形)を用意。Dockerfileにはアプリコードやライブラリ、ベースイメージに関することが記載される。
※Dockerfile例
FROM ruby:2.7
#Rubyの2.7を使う
RUN mkdir /var/www
#RUNはコマンドの実行。以下のディレクトリを作れという意味
COPY main.rb /var/www
#さっき作ったmain.rbを/var/wwwの下に置く
CMD ["ruby", "/var/www/main.rb"]
#Dockerのイメージを起動した時に実行するコマンドを指定している。rubyでmain.rbを実行
これでイメージを作る下準備ができた
イメージを作る
docker image build -t sample/webrick:latest .
-t → 今後使いやすくするためにタグをつける
. → 今いるディレクトリのDockerファイルを参照する
イメージが作れたか確認するコマンド
docker image ls (今回はsample/webrickがある)
コマンド確認
docker --help
docker image --help
イメージからコンテナを作成し起動
docker container run
(今回)
docker container run -d -p 8000:8000 --name webrick sample/webrick:latest
-d → バックグラウンドで実行できる。ターミナルが使えるように
-p → ポートの指定。左側が自分のポートで、右側がDockerのポート。今回は自分の8000番ポートをDockerの8000番ポートに接続させる。
--name → 名前をつけておくと後々楽(今回はwebrick)
最後に指定のイメージ
コンテナのライフサイクル
作成→起動→停止→削除
コンテナが今どうなっているかの確認
docker container ls (起動中のコンテナ確認)
docker container ls -a (停止中のコンテナも含め確認)
コンテナの停止と削除
停止
Ctrl + C or
docker container stop webrick(コンテナ名)
削除
停止後に
docker container rm webrick(コンテナ名)
コンテナ操作でよく使うコマンド
異常が起きた時にログを見て分析する
docker container logs webrick(コンテナ名)
実行中のコンテナで別のコマンドを実行したい時
docker container exec webrick(コンテナ名) ruby -v
使わないイメージやコンテナが溜まってハードディスクを圧迫するので後片付けしたい時
docker system prune -a(all)
Dockerfileを作ろう
Dockerfile振り返り
アプリケーションやライブラリ、ベースイメージなどの情報を書き込み、これを基にイメージを作成する
今回の前提
Dockerというディレクトリで作業し、この中にはsrcディレクトリ、さらにその中にはGemfileがある。目標はsinatraを動かすこと。
docker/src/Gemfile
・
・
gem "sinatra"
srcと同じ階層にDockerfileを作成
Docker/src/Dockerfile
FROM ruby:2.7
#rubyというイメージの2.7を指定
WORKDIR /var/www
#ディレクトリは何でもいい。作業をする場所。ディレクトリがない場合は作ってくれる
COPY ./src /var/www
#srcディレクトリ以下のファイルを/var/wwwの下にコピー。アプリケーションコードをDockerにコピーできる
CMD ["/bin/bash"]
#Docker起動時にbashを開く
Dockerfileを作ったので次はイメージを作成
docker image build -t sample/sinatra:latest .
コンテナを作成し起動
docker container run -it -p 4567:4567(sinatraのポート番号) --name sinatra
-v ${PWD}/src:/var/www sample/sinatra:latest
-it → Dockerにインタラクティブモード(対話型)でコンテナを起動させることを明示。shellを起動する際にいる
-v → ボリュームのオプション。コロンから左が自分、右がDocker側。自分のディレクトリのsrc以下をDocker内の/www以下に共有する。これをしないと更新した時に、イメージを作り直さないといけない。
上のコマンドを実行するとbashが開く。自分がいる場所は/var/wwwだが、ローカルの変更内容が共有されていることがわかる。
ライブラリのインストール
手法(開発プロセス):
一度Dockerのコンテナ内に入ってコマンドを実行し、うまくいったらそれをDockerfileに反映させる。
現在はbashが開いている
bundle config --local set path 'vendor/bundle'
vendor/bundleにライブラリの中身をインストールしてという意味
bundle install
Gemfileの中身がインストールされる
Hello worldを表示
app.rbというファイルを作り、そこにHello worldを表示するコードを記述
その後ターミナルで
bundle exec ruby app.rb
Gemfileを使った処理を動かす時はbundle execをつける。
WebrickというWebサーバーが立ち上がる。localhost:4567にアクセスするとHello worldが記述されている。
続いてこれをDockerfileに反映させる。
Docker/src/Dockerfile
FROM ruby:2.7
WORKDIR /var/www
COPY ./src /var/www
RUN bundle config --lcoal set path 'vendor/bundle'
RUN bundle install
#先ほど手動でやったことと同じことが実行される
#1行で書く方法
RUN bundle config --lcoal set path 'vendor/bundle' \
&& bundle install
CMD ["bundle", "exec", "ruby", "app.rb"]
#書き換え。コンテナ起動時にbundle exec ruby app.rbが実行される。スペース区切りをコンマで区切る
Docker Compose
Railsの開発環境を構築
Docker Compose
複数のアプリケーションをまとめて操作
Docker Compose例:
docker-compose.yml
version: '3'
services:
db: #それぞれ設定
image: mysql8.0
web: #それぞれ設定
build:
depend_on:
- db
基本操作
イメージのビルド
docker-compose build
コンテナの作成と起動
docker-compose up -d(バックグラウンドで実行)
コンテナを停止・削除
docker-compose down
その他のよく使う操作(1)
コンテナの一覧を表示
docker-compose ps
ログを表示
docker-compose logs
その他のよく使う操作(2)
コンテナを作成してコマンドを実行(1からコンテナを作成し実行)
docker-compose run <サービス> <コマンド>
起動中にコンテナにコマンド実行(今あるコンテナに実行)
docker-compose exec <サービス> <コマンド>
開発
全体の流れ
1.Docker関連のファイルを用意
2.初期設定
3.起動
4.追加操作
Dockerfile
コードを大まかに(詳しくは動画を確認)
FROM ruby:2.7
RUN ・・・
#今回必用なライブラリを指定(今回はnode.jsとかyarnとか)
WORKDIR /app
COPY ./src /app
#ローカルのソース(Railsのソースコード)を/appにコピー
RUN bundle config --local set path 'vendor/bundle' \
&& bundle install
#Ruby関連のライブラリのインストール
Gemfile
gem 'rails', '~> 6.1.0'
Docker-compose.yml
version: '3'
services: #2つのサービスを定義
db: #今回はMYSQL
image: mysql8.0
command: #MYSQLの認証形式に関する設定
---default-authentication-plugin=mysql_native_password
volumes: #コロンから左がローカルのディレクトリ、右がDockerのディレクトリ ディレクトリを同期
- ./src/db/mysql_data:/var/lib/mysql
environment: #環境変数の設定(パスワードの設定)
MYSQL_ROOT_PASSWORD: password
web: #今回はRails
build: . #ベースのイメージとして同じディレクトリにあるDockerfileを参照する
command: build exec rails s -p 3000 -b '0.0.0.0'
#railsのサーバーを起動する
volumes: #同期の設定
- ./src/app
ports:
- "3000:3000"
depends_on: #依存関係(webがdbに依存。接続先のホスト欄をIPアドレスではなくdbと省略できる)
- db
初期設定
docker-compose run web rails new . --force --database=myspl(データベースを指定)
コマンドを実行すると新しいGemfile(+他のRailsのファイル)ができている。
Gemfileが更新されたり、Dockerfileの内容が更新された時は、イメージをbuildする。
docker-compose build
次はデータベースの設定
src/config/database.yml
初期状態:
default: &default
・
password:
host: localhost
・
書き換え後:
default: &default
・
password: password (docker-compose.ymlのenvironmentのとこ)
host: db (docker-compose.ymlのdepends_onのとこ)
・
続いてデータベースの作成
docker-compose run web rails db:create
起動
docker-compose up
localhost:3000にアクセスでrailsの画面が出る
追加の操作
サーバーの止め方
Ctrl + C or
docker-compose down (いっぺんに停止)
再度起動
docker-compose up -d (バックグラウンドで実行)
コンテナの一覧を表示
docker-compose ps
ログを見る
docker-compose logs
コンテナ内でコマンドを実行したい時(例: bash)
docker-compose exec web /bin/bash (bashが起動しコンテナの中に入れる)
GemfileやDockerfileの修正を反映させたい時
docker-compose build (イメージを作り直す)
docker-compose up -d (もう一度コンテナを作成・起動)
本番環境に公開しよう
本番環境で使わないと、手動でライブラリを入れないといけない。面倒だし、本番とローカルの差異が発生する。
今回はHerokuを使い、Heroku上でDockerコンテナを起動することで本番に公開する。
全体の流れ
1.事前準備
2.Herokuにログイン
3.Herokuアプリを作成
4.DBを追加・設定
5.Dockerfileを本番環境用に修正
6.Dockerイメージをビルド・リリース
7.機能追加
事前準備
githubの登録 + ユーザー名とメールアドレスを設定
Herokuの会員登録 + Heroku CLIインストール
Herokuにログイン
適宜確認
Herokuアプリの作成
リリースしたいものをアプリという単位で管理している
DBの追加・設定
DBの追加
heroku addons:create cleardb:ignite -a rails-docker-kyt
DBの設定
本番環境のデータベースの接続先等を変更する(環境変数を使う)
Dockerfileを本番環境用に修正する
処理が本番とローカルでちょっと変わってくる
トップディレクトリにstart.shというファイルを作成。ここに本番環境特有の処理を入れておく。
修正内容
環境変数を設定
FROM ruby:2.7
ENV RAILS_ENV=production ←ここ
一番下にいくつか処理を追加
・
・
COPY start.sh /start.sh
#さっき作ったファイルをDocker側ルートディレクトリ直下にコピー
RUN chmod 744 /start.sh
#実行権限を与える
CMD ["sh", "/start.sh"]
#起動直後にファイルを実行
start.shに処理を記述
/start.sh
#!/bin/sh シェルスクリプトのファイルなのでおまじない的に書く
if [ "${RAILS_ENV}" = "production" ]
then
bundle exec rails assets:precompile
fi
#Dockerfileはif文が使いにくいのでこっちのファイルで実行している
#Railsは本番環境でコンパイルしなければならないので上記のコードを書く
bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0
#Railsサーバーを起動する。ポートがあればそれを使い、なければどこからのIPアドレスでもOK
その後に環境変数の追加コードを書く。
ちなみにローカルでサーバーが起動している、Herokuで起動しない可能性があるので、docker-compose downでサーバーを削除しておく。
Dockerイメージをビルド・リリース
Dockerイメージをビルドして、コンテナレジストリの方にpushする
heroku container:push web -a rails-docker-kyt
コンテナレジストリからHerokuの方にリリースする
heroku container:release web -a rails-docker-kyt
DBのマイグレーション(テーブルを更新したい時)
heroku run bundle exec rake db:migrate RAILS_ENV=production -a rails-docker-kyt
機能追加
今はページがないのでサイトに警告が表示されているので作る。
まずは開発するようにサーバーを立ち上げる。
docker-compose up -d
次にコントローラを作る
docker-compose exec web bundle exec rails g controller users
ルーティングの設定
routes.rb
get '/', to: 'users#index'
コントローラの記述
users_controller
def index
end
ビューを作成
users/index.html.erb
<h1>Hello world</h1>
ローカルで作成が完了したので、Herokuに反映させる。ローカルサーバーは落としておく。
heroku container:push web -a rails-docker-kyt
heroku container:release web -a rails-docker-kyt
問題点:
修正とかエラーがあるたびに、pushからやり直すのが鬼のように面倒臭い。そこでCI/CDでテストやデプロイを自動化する。
CI/CD
現在の問題点。手動デプロイがかなり面倒臭い。
用語説明
CI(継続的インテグレーション):
コードが変更されるたびに、ビルドやテストを自動で実行する。
CD(継続的デリバリー):
変更に対しレビューをして、マージされたら自動でデプロイする。
CI/CD構築サービス
CircleCI:
ビルド・テスト・デプロイをクラウド上で行ってくれるCI/CDツール。
全体像
ローカルからGitHubにコードがアップされるたびに、自動でビルドとテストを行う。
↓
テストを終え、レビューしコードがマージされたら、自動でdockerコンテナをデプロイする。
全体の流れ
1.GitHub
2.CI
3.CD
GitHub
・GitHub上でリポジトリ作成
・Gitでコードを管理
・.gitignoreを追加
・コミット、プッシュ
.gitignoreを追加
.gitignoreとはバージョン管理する必要のないものを管理下から外せる。データベースの接続先情報などの機密情報やインストールしたライブラリのコードなどのバージョンを管理する必要のないものを指定しておく。.gitignoreファイルはRailsがデフォルトで用意してくれているがプロジェクトの直下に置かなければならないので、以下のコードを実行。
mv src/.gitignore .
mv src/.gitattributes .
またsrc直下に.gitファイルがあると二重管理になりエラーが起こるので削除しておく。
rm -rf src/.git/
次に.gitignoreファイルを修正。srcの直下に移動したので、全ての文頭にsrcをつけていく。
またMYSQLのデータも管理する必要がないので追加しておく
例:
.bundle
↓
src/.bundle
src/db/mysql_data
CI
GitHubにプッシュされたタイミングで、毎回テストが入るようにCIを構築する。
・テストコードを記載
・CircleCIに登録
・プロジェクトを登録
・configを設定
・環境変数を設定
・GitHubにプッシュ
・テストを修正
テストコードを記載
users_controller_test.rbに落ちるテストを記載
docker-compose up -d
docker-compose exec web bundle exec rake test
結果はred
CircleCIに登録
GitHubでログイン
プロジェクトを登録
Projectsのページにある、現在のアプリのリポジトリからSer Up Projectをクリック。その後、Add Configをクリック。
※CircleCIに関して、.circleci/config.ymlの中に設定を書き込むことで動作する。これがないと動かない。
configの設定
直下に.circleciディレクトリ、その下にconfig.ymlファイルを作成。
.circleci/config.yml
詳細なコードに関しては動画を参照
・バージョンを設定
・orbs: jobを事前に定義しシェアできる。便利な記法がjobのところで使える
・jobsでbuildとtestを定義(詳細は動画で要確認)
・workflowsのところで、何を行うか(今回はbuildとtest)、どっちを先にするかなどを記載
環境変数を設定
master.keyがRailsを動かす際に必要だが、.gitignoreに指定されている。流出してはいけないので、それ自体はいいことだが、ソースコードを動かす上ではこの値が必要なので環境変数として指定しておく。
heroku config:add RAILS_MASTER_KEY='(ここに値を貼り付け)' -a rails-docker-kyt
GitHubにプッシュ
add、コミット、プッシュまで(プルリクの流れが説明されてるので、後で見返す)
予想通りテストは落ちている
テストを修正
assert falseをtrueに。これでgreenになる。
CD
mergeされたら自動でHerokuにデプロイされる
流れ
・configを修正
・環境変数を設定
・Viewファイルを修正
・GitHubにプッシュ
・マージ、デプロイ
configを修正
.circleci/config.yml
詳細は動画を確認
・orbsにheroku: circleci/heroku@1.2.3を追記(後々便利な記法が使えるように)
・jobsに以下を追記
- deploy:
requires:
- test
filters:
branches:
only: main
(deployのjobはmainブランチに変更があった時のみ実行)
・deployのjobを定義(詳細は動画を確認)
環境変数の設定
CircleCI上で設定する
Projects→現在のリポジトリ→Project Settings→Environment Variables
→Add Environment Variable→NameとValueを設定
(今回は名前やAPIキー)
Viewファイルを修正
deployされたことがわかるように書き換え
GitHubにプッシュ
マージ、デプロイ