LoginSignup
1

【自主勉強】dockerの自主勉強及び実行

Last updated at Posted at 2022-11-11

dockerについて。

インフラ環境を構築するために、Dockerを活用させていくためにも、まず勉強していく必要がある。
今回はそれを学ぶために、自習してきた内容を記録する。

ここの内容を参考にする
https://www.youtube.com/watch?v=lZD1MIHwMBY

環境構築

今回使用するものはこれ。

  • iTerm2
  • Docker
  • VScode
  • Git

iterm2のブラウザを開いて、ダウンロードする。zipから、簡単に出すことができる。
これを使って、Linuxとかのコマンドを使う。

VScodeの拡張で便利なのは?

  • japaneselanguage
  • docker

gitのインストール
ブラウザで検索し、download for mac を押してみる。

Macの場合、Homebrewを使う。

homebrewを使ったら、

brew install git

を用いる。入ったら、

git --version

で、コマンドが表示されたらOK

dockerのインストール

DockerDesktop for mac を用いる。
これをダウンロード。そして、開いていく。
https://www.docker.com/products/docker-desktop

クリックすると起動する。
dockerが既に動いているかを確認するには、上のメニューバーを見ると、クジラが映る。

この状態で、このように打てば、dockerのコマンドがあるのを確認できる。

docker --version
Docker version 20.10.10, build b485636

Linuxを用いる。

dockerにはLinuxコマンドを用いる。
コンピュータやサーバの操作をする時に、使えないと不便。これを知っていれば、Dockerやサーバの操作をする時に便利になる。

一度身につければ、変わらずに使い続けることができる。

dockerは開発環境を整えるもので、OSからコードまでをセットにしたもの。
Docker使う時も、OSはLinuxなので、Linuxを学ぶ必要がある。コマンドを使って。ファイルの一括操作とかができるので、便利らしい。

シェルはLinuxのコマンドを受け取って、結果を出力するためのソフトウェア。

  • つまり、ユーザーとLinuxの仲介役である。
  • そのコマンドを入力する画面が、ターミナル

ターミナルはあくまで画面担当。シェルはコマンドを解釈して、Linuxに伝える。

実際にLinuxコマンド使う。

  • lsコマンド。

    • 現在いるディレクトリなどの一覧を見ることができる。
  • pwdコマンド

    • 今、自分がいるディレクトリを表示
  • cdコマンド

    • ディレクトリを移動する。
    • 〜ならホームディレクトリ
  • mkdirコマンド

    • ディレクトリを作るコマンド
    • mkdir dockerとすると、
    • dockerのディレクトリ(フォルダ)を、現在のディレクトリ内に作る。
  • touchコマンド

    • 新規の空ファイルを作成することができる。
  • echoコマンド

    • echo 'Hello' > tmpとすると、tmpの中にHelloの文字を見れる。
  • catコマンド。ファイルの中身を見る

  • lessコマンド

    • lessコマンドは、全画面で文字を表示する。長い時に便利。
    • qキーで終了する。
  • mvコマンド(ムーブ)

    • ファイル名を変更するコマンド
    • mv tmp tmp1とすると、
    • tmp -> tmp1 に変更される。
  • rm(リムーブ)コマンド

    • ファイル名を削除するコマンド

Dockerを使ってみる。

使いながら、仕組みも学ぼう。

以下コマンドを、iterm2にて入力

docker run hello-world

こんな感じで、Hello from Dockerと来ればOK.

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.

これは、

  1. ハローワールドのイメージ(花形)から
  2. コンテナを作る。
  3. そのコンテナを起動している。

もっと具体的な流れ。

クライアント(依頼主)が、

  1. docker runというコマンドを渡す。
    • それをクライアントが、デーモンにコマンドを実行するように伝える。
  2. それをデーモンが受け取る。
    • バックグラウンド上で動作し続けるアプリケーションのこと
  3. デーモンは、Dockerのイメージをレジストリから引っ張ってくる。(ローカルに持ってきてくれる)
    • レジストリは、イメージをオンライン上で保存しておく場所のこと。
  4. イメージを元に、コンテナを作っていく。
  5. ターミナルに、コンテナを起動した結果Hello from Dockerが表示される。

Dockerでアプリを作って実行する。

Dockerというのは、

  • イメージと
  • コンテナ
    の操作になっている。

Dockerを用いる開発の基本の流れはこう。

  1. アプリコード&Dockerファイルの作成()
  2. ここからイメージを作る。
  3. イメージを元に、コンテナを起動

     

アプリケーションの用意

Rubyの簡単なサーバを作る。

VScodewを開く。

main.rb

というファイルを作成する。
rubyの、webrickというものを用いると、簡単にWebサーバーを立ち上げることができる。

ウェブサーバーとは、HTTPリクエストを受け取り、レスポンスを返すサーバーのことである。

require 'webrick'

server = WEBrick::HTTPServer.ner(
DocumentRoot: './',
BindAddress: '0.0.0.0',
Port: 8000

)

server.mount_proc('/') do |req,res|
    res.body = 'hello'
end

server.start

トップページが表示されたら、ハローと表示されるファイルである。

Dockerfileを作成する。

イメージの雛型になる。

Dockerfileというファイルを作り、以下のように作成

  • FROMで、ruby2.7というドッカーのイメージを使うことを指定する。
  • RUNという変数で、Linuxのコマンドを指定する。ここでは、ディレクトリを作成する。
  • main.rbを、 /var/wwwの下におく。
  • CMDで、実行するコマンドを指定する。["ruby","/var/www/main.rb"]で、rubyで、main.rbを実行するということを表す。

イメージを作成する。

ドッカーのイメージの作成は、コマンドで行う。

docker image build -t sample/webrick:latest .
docker image build
は、ドッカーのイメージをビルドする。

-tオプションで、タグを指定する。
ここでは、sample/webrick:latestというタグを指定する。latestはバージョンの名前とする。

最後の.で、現在のディレクトリを参照する。つまり、現在のディレクトリのDockerfileを参照するという事。

イメージを作れたかを確認するのは、以下コマンドで確認できる。

docker image ls

こんな感じになる。

itoudaiware@itoudaiwarenoMacBook-Pro docker % docker image ls
REPOSITORY       TAG       IMAGE ID       CREATED              SIZE
sample/webrick   latest    bd853182e720   About a minute ago   812MB
hello-world      latest    18e5af790473   8 weeks ago          9.14kB

また、docker --helpで、コマンドを確認できる。

コンテナ起動

イメージからコンテナの作成&起動をするには、docker container runを使う。

今回なら、以下コマンドになる。
docker container run -p 8000:8000 --name webrick sample/webrick:latest

解説する。

  • docker container runで、作成と起動を同時に行う
  • -pで、ポートを指定する。ここでは、ローカルの8000ポート(最初の8000)を、dockerの8000ポート(次の8000)に接続させている。
    • ポートは、アプリケーションの宛先みたいなもの。
    • コンテナは閉じた環境なので、Dockerの中のポート番号につなげる必要がある。
  • 最後に、イメージ名を指定している。

実行すると、こんな感じになる。
うまくできていると思われる。

itoudaiware@itoudaiwarenoMacBook-Pro docker % docker container run -p 8000:8000 --name webrick2 sample/webrick:latest
[2021-11-21 06:19:15] INFO  WEBrick 1.6.1
[2021-11-21 06:19:15] INFO  ruby 2.7.4 (2021-07-07) [aarch64-linux]
[2021-11-21 06:19:15] INFO  WEBrick::HTTPServer#start: pid=1 port=8000

確認するには、自分のブラウザで確認する。localhost:8000(自分のパソコンの8000)にアクセスする。
こんな感じで確認できる。

コンテナのライフサイクル

先ほどの流れで、起動と作成を行なった。停止と削除を行う。

まずは、ターミナルでCtrl +C

docker container ls で、現在起動中のコンテナのリストを見る。

docker container ls -aで、停止中のものも見る。

コンテナを停止させるコマンドはこれ。
webrickは、コンテナ名
docker container stop webrick

削除させるにはこれ。webrickは、コンテナ名。

docker container rm webrick

また、バックグラウンドでコンテナを実行させるには、-dのオプションを用いる。
これで、ターミナルも使う事ができる。

docker container run  -d -p 8000:8000 --name webrick sample/webrick:latest

よく使うコンテナ関連のコマンド

ログ

これは、デバッグや、問題があった時によくみる。

docker container logs webrick(コンテナ名)

これで、コンテナに対するログが見れる。

itoudaiware@itoudaiwarenoMacBook-Pro docker % docker container logs webrick
[2021-11-21 06:32:16] INFO  WEBrick 1.6.1
[2021-11-21 06:32:16] INFO  ruby 2.7.4 (2021-07-07) [aarch64-linux]
[2021-11-21 06:32:16] INFO  WEBrick::HTTPServer#start: pid=1 port=8000
172.17.0.1 - - [21/Nov/2021:06:32:43 UTC] "GET / HTTP/1.1" 200 5
- -> /
172.17.0.1 - - [21/Nov/2021:06:32:50 UTC] "GET / HTTP/1.1" 200 5
- -> /
itoudaiware@itoudaiwarenoMacBook-Pro docker %

別のコマンドを実行する時

docker container exec webrick ruby -v
  • exec の後に、コンテナ名を入れる
  • その後、実行したいコマンドを入力
    • ここではルビーのバージョンを見る。

これで、作ったコンテナの中でコマンドを使う事ができる。

後片付け

pruneというコマンドを用いる。

docker system prune -a

-a を用いると、今使っていないコンテナ、ネットワーク、イメージを全て削除することができる。

Dockerfileの作成

Dockerのイメージをどうやって作る?
Dockerfileを作成する。
これが作れれば、自分で開発環境が作れる…!

sinatora

今回は、sinatraという、ルビーの軽いFrameworkを用いる。
そして、Gemfileというものを作成していく。

これは、ライブラリのパッケージ管理ツールである。その中に、インストールするGem(今回はsinatraというライブラリ)を指定してやる。

Gemfileの中はこんな感じ


source "https://rubygems.org"

git_sources(:github) {|repo_name| "https://github.com/#{repo_name}"}

gem "sinatra"
  1. その後、Dockerfileを作る。
    基本的にDockerファイルは、コンテナの立ち上がりに必要なコマンドを順に記載していくイメージ。
  • FROM ruby:2.7で、ruby2.7のイメージを指定する。

  • WORKDIR /var/wwwは、ワークディレクトリ。作業する場所を指定する。特に指定はない。

  • WORKDIR /appも指定する。

    • ディレクトリがない時、ディレクトリを作ってくれる。
  • ソースコードを、コンテナ内にコピーする。COPY ./src /var/wwwで、srcを、wwwの中にコピーする。

    • 今回、srcディレクトリの中にアプリのソースファイルをいれているので、それをコピーしている。
  • CMD ["/bin\bash"]は、シェル(bash)を起動させるコマンド。

    • これで一回Dockerのコンテナの中に入って、その後うまく行ったコマンドがあれば、それをDockerfileに記載していく。
  1. イメージを一度作成する。
    sample/sinatra:latest というタグを設定する。
docker image build -t sample/sinatra:latest .
  1. コンテナを作成&起動
  • シェルのようなインタラクティブなコンテナを起動する時は、-itを使う。これを使う事で、インタラクティブモードで立ち上がる。
  • ポート番号の指定は、シナトラはデフォルトで4567になるので、ローカルも4567としておく。
  • 参照しやすいように、--nameでコンテナの名前を付ける。sinatraとする。
  • -vで、ソースコードの共有をする。
    • ${PWD}/src:/var/www
    • これで、自分の現在のディレクトリ下のsrcディレクトリを、コンテナ側の/var/wwwと同期するという意味。

これを行わないと、**何かソースコードの変更をした時に、いちいちイメージを作り直さないとソースコードがイメージに反映されない。**それは面倒臭いので、-vをつけると、ローカルの指定したディレクトリに合わせて中身が変わる。

  • イメージ名を指定する。sample/sinatra:latest
docker container run -it -p 4567:4567 -v ${PWD}/src:/var/www sample/sinatra:latest
  1. 実行すると、プロンプトが変わる。つまり、bashが起動したという事。さらに、-itで指定したので、既にコンテナの中に入っている。
itoudaiware@itoudaiwarenoMacBook-Pro sources % docker container run -it -p 4567:4567 -v ${PWD}/src:/var/www sample/sinatra:latest
root@75a4d2fd2236:/app#

そして、Gem fileが中にいる。catで見てみる事もできる。これは、ローカル側のGemfileになっている。

root@75a4d2fd2236:~# cd /var/www
root@75a4d2fd2236:/var/www# ls
Gemfile
root@75a4d2fd2236:/var/www# cat Gemfile

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}

この状態で、Gemfileを変更したりすると、中身も変わってくる。変更して保存すると、こんな感じで変更されているのがわかる。

gem "sinatra"root@75a4d2fd2236:/var/www# cat Gemfile
# frozen_string_literal:true
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}

コンテナにて、gemをインストールしていく。

以下コマンドで、vendor/bundleにインストール先を指定する

bundle config --local set path 'vendor/bundle'

これができたら、インストールコマンドを実行

bundle install

うまくいったらこんな感じ。

省略。
Bundle complete! 1 Gemfile dependency, 7 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

そして、アプリのコードを作成していく。

srcの下に、app.rbを作成する。
受け付けるIPアドレスは、0.0.0.0で全て。get '/'で、トップページに来たらHello worldで、ハローワールドを表示する。

require 'sinatra'

configure do 
    set :bind, '0.0.0.0'
end

get '/' do
    'Hello world!!'
end

この状態で、このアプリケーションを実行。bundleを使用した時は、前にbundleを付ける。そして、rubyのファイル中の、app.rbを実行する。

bundle exec ruby app.rb

ここで、ブラウザにアクセスする。
すると、アクセスすることができた!

ここまでの処理を、Dockerfileで実現する。

先ほど実行した、bundle config --local set path 'vendor/bundle'と、bind installを、RUN の引数に指定して記載する。ちなみに、バックスラッシュ
や&&で、一つにまとめることも可能

そして、実行するファイルを書き直す。
先ほどはbash(/bin/bash)のみだったが、

  • bundle
  • exec
  • ruby
  • app.rb(file名)

を記載する。

CMD ["bundle","exec","ruby","app.rb"]

これで、コンテナが起動した瞬間に、これらが実行されるようになる。

ちなみに、linuxのコマンドではbundle exec ruby app.rbと、スペース区切りで行なっていたが、
CMDの中は、""と,を用いて区切っていく。

コンテナ作り直し

  1. Ctrl + C で一度やめる
  2. exitで、コンテナから抜ける
  3. コンテナを削除する。
docker container rm sinatra
  1. 新しく、イメージを作る
docker image build -t sample/sinatra:latest .
  • この時、こんな感じでエラーが出た。

gem "sinatra"root@75a4d2fd2236:/var/www# bundle config --local set path 'vendor/bundle'
root@75a4d2fd2236:/var/www# bundle install

[!] There was an error parsing `Gemfile`: Undefined local variable or method `git_sources' for Gemfile. Bundler cannot continue.

 #  from /var/www/Gemfile:4
 #  -------------------------------------------
 #
 >  git_sources(:github) {|repo_name| "https://github.com/#{repo_name}"}
 #
 #  -------------------------------------------

インストールしようとしているディレクトリにはGemfileがないらしい。
そのため、WORKDIR/appを、WORKDIR /var/wwwの上にすることで、問題なく実行できた。

WORKDIR /app
WORKDIR /var/www
  1. もう一度コンテナを起動する。-itは今回必要ないので、削除しておく。
docker container run -p 4567:4567 -v ${PWD}/src:/var/www sample/sinatra:latest

再度実行しても、こんな感じで問題なく出力されている。

docker container run -p 4567:4567 -v ${PWD}/src:/var/www sample/sinatra:latest

まとめ

Dokcerfileの作り方は基本的には、

  1. まずコンテナに入る。
  2. コンテナ内で、コマンドを実行
  3. そのコマンドがうまくいけば、Dockerfileに記載する。

Dockercomposeで、Rails開発環境を構築する。

Webサービスは、

  • アプリケーション
  • DB
  • Webサーバ
    といった、**複数のアプリを連携させる必要がある。**複数のコンテナを連携させたりするために、DockerComposeを用いる。

DockerCompose

複数のアプリケーションをまとめて操作できる。連携も簡単にできる。
servicesというものの下に、dbやwebなど指定していく。

基本操作コマンドはあまり変わらない

  • イメージのビルド
docker-composebuild
  • コンテナの作成・起動(-dはバックグラウンドで起動)
docker-compose up -d
  • コンテナを停止・削除
docker-compose down
  • コンテナの一覧表示
docker-compose ps
  • コンテナのログ表示
docker-compose logs
  • コンテナを作成して、コマンドを実行。つまりこれを使うと、コンテナを一から作り直す。
docker-compose run <サービス名><コマンド>
  • 起動中のコンテナにコマンドを実行
docker-compose exec <サービス> <コマンド>

実際に作成する。

Dockerfile作成

今回、ディレクトリに以下のファイルを作成する。

  • src/Gemfile
  • docker-compose.yml
  • Dockerfile

今回のDocker fileの中身はこんな感じ。

FROM ruby:2.7

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -  && echo "deb https://dl.yarnpkg.com/debian/ stablemain" | tee /etc/apt/sources.list.d/yarn.list && apt-get update -qq && apt-get install -y nodejs yarn

WORKDIR /app
COPY ./src /app
RUN bundle config --local set path 'vendor/'

ここのRUNで、nodejsとyarnを外部からインストールしている。
Gemfileなどをまとめている。

Gemfileの中身はこんな感じ

source 'https://rubygems.org'

gem 'rails', '~> 6.1.0'

gemで、railsのみを指定している。

次に、docker-compose.ymlの中身をみる。
ここには、servicesというものがあり、その下に

  • db 

  • web
    の二つの要素(サービス)が定義されている。

  • dbには、mysqlのイメージを今回使用している。

    • commandというのは、認証形式に関する設定
    • volumesは、左側./src/db/mysql_dataがローカルのディレクトリで、右側/var/lib/mysqlが、コンテナ側のファイルと同期するという設定になる。
      mysqlのコンテナが消えると、データを入れ直したりする必要が出てくるので、
      同期しておく。
  • environmentは環境変数。mysqlのpasswordを指定しておく。

  • webには、Railsを使用している。

  • build: .は、カレントディレクトリのDockerfileを参照するという事

  • commandは、実行するコマンド。ここではRailsのサーバーを、ポート3000番で起動している。

  • volumesは、.src内を、/appと同期させるという意味。

  • portsはローカル、3000。

  • depends_onは、依存関係DBサービス。

    • **これは、webサービスは、DBサービスに依存しているよという意味になる。**これをしないと、Rails -> Mysqlに接続する時に、dbとするだけで接続できる。(本来はIPアドレスが必要になる。)

初期設定

以下コマンドを実行する。これは、rails newコマンドで、railsの雛形が作成される。

 docker-compose run web rails new . --force --database=mysql

なお、M1チップのMacでは、エラーが出た。

ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries

そのため、docker-compose.ymlに、以下platform情報を追記した。

    platform: linux/x86_64 (ここ)
    image: mysql:8.0
    command:

インストールが完了すると、srcの中に、Railsのデフォルトのファイル群達が追加された。

その中の、Gemfileが新しく更新される。

なので、一度、イメージを更新しておく。

docker-com pose build

これでRailsの雛形を作り、イメージを作り直す事ができた。

DBの内容を変える

src/config/database.yml
をみる。その中のpasswordの部分を、docker-compose-ymlの方のenvironmentで指定したものにする。

次に、localhostをDBにする。接続先情報を修正する。

host: localhost
をいかに変更
host: db

DBを作る

これで、webのサービスに対して、railsのdb:createというコマンドを実行する。という意味。

docker-compose run web rails db:create

こんな感じで二つ造られる。

itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % docker-compose run web rails db:create
Creating rails_docker_web_run ... done
Created database 'app_development'
Created database 'app_test'
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker %

起動させる。

以下コマンドで、サーバを起動させる。

docker-compose up

ターミナルの画面を見ると、おそらく起動してそう。

ブラウザで、Railsの3000ポートを見てみる。

起動した!!やったね!

追加の操作

サーバの止め方は、Ctrl + Cでもできるが、もう一つおこなってみよう。

  1. もう一つタブを出し、さっきdocker-composeを実行したディレクトリに移動。
  2. そして、以下コマンドを実行すると、停止して削除する事ができる。
docker-compose down
  1. もう一度実行する時は、upとする。-dをつければ、バックグラウンドになる。
docker-compose up -d
  1. コンテナの一覧と状況を見るには、docker-compose psを使う。
  2. ログを見るには、docker-compose logs
  3. コンテナ内でコマンドを実行する時は以下を実行
docker-compose exec web /bin/bash
  1. 修正を反映させる時。
  • docker-compose build で、イメージを再作成
  • docker-compose up で、コンテナを再作成

本番環境でDockerコンテナを公開

今までのやつは、ローカルでつかう手順だった。
本番環境で使えるようにしよう!
本番環境で使わないと、思わぬ差異が発生したりする。

本番環境でも使えば、同じコンテナを起動させるだけでOK.いちいちライブラリを入れたりする必要がない。

なので、本番環境でdocker運用する所まで行おう!

今回は、Herokuというホスティングサービスを用いる。https://jp.heroku.com

  • サーバー、OS、ミドルウェアを自動で構築してくれるサービス。
  • そこにコンテナを起動させる事で、本番に公開する。

流れはこんな感じ。

  1. Herokuにログイン
  2. Herokuアプリを作成
  3. DBを追加&設定
  4. Dockerfileを本番環境用に修正
  5. Dockerイメージをビルド&リリース
  6. 機能追加

事前準備

まず、Githubが必要なので、登録する。
https://github.com

githubの設定

そして、GitHubが、Herokuで使えるようにする。

  1. ターミナルを開きGithubのユーザ名を入力
git config --global user.name "itohdaigo"
  1. ギットハブで登録したemailを登録する。
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % git config --global user.email "XXXXXXX@gmail.com
  1. 登録した方が便利。マージの際に、ファストフォワードが起こらないようにする。
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % git config --global merge.ff
 false
  1. プルした時に、リベースするというもの。
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % git config --global pull.reb
ase merge
  1. 以下コマンドで確認できる。
git config --list

Herokuの設定

ホームページにアクセスし、新規登録を行う。
https://jp.heroku.com
自分はなんかもう作ってあった。
これのログインには、Authenticatorから、認証コードを読み取る必要があった。

  1. ログインしたら、AccountSettingsをみる。

  2. billingの所で、クレジットカードの登録が必要(今回は、無料の範囲内で行う。)
    アドオンでmysqlを登録するときに、クレジットカードが必要

  3. HerokuCLIという,コマンドでHerokuを操作できるものをインストールする。
    https://devcenter.heroku.com/ja/articles/heroku-cli
    自分はmacなので、このコマンドでインストールする。

brew tap heroku/brew && brew install heroku

HerokuにCLIでログインする。

以下コマンドでログイン

heroku login

そして、適当なキーを押したら、ブラウザが出てくるので、Loginを押す。

成功したら以下のようにでる。

Logging in... done
Logged in as bladrain.32@gmail.com

Herokuアプリを作る。

運用したいサービスを、アプリとして作成する。
以下コマンドを実行createの後は、アプリ名である。diegoは自分の名前。このアプリ名は、世界中の人と重複してはいけない。

heroku create rails-docker-diego

DBの追加・設定

Herokuでは、今作ったアプリに、DBをアドオンとして追加するという形になる。
mysqlは、Herokuでは一つだけcleardbというのが無料なので、今回はそれを使用する。

ただし、無料枠のmysqlは,バージョンが5系しかない。dockerのイメージではもっと新しいのを使っているので、本当は揃えた方がいい。今回は特に問題がないので、そのまま使用する。

heroku addons:create cleardb:ignite -a  rails-docker-diego
  • -aは、アプリケーション名

次に、接続先情報を変える。
今回、環境変数にして、接続先情報を渡すようにする。

DBに不正侵入されてしまう恐れがあるので、環境変数にいれる。

config/databese.yamlを見てみる。一番下の、productionを変更する。

production:
  <<: *default
  database: app_production
  username: app
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>

これを、こんな感じにする。

production:
  <<: *default
  database: <%= ENV['APP_DATABASE'] %>
  username: <%= ENV['APP_DATABASE_USERNAME'] %>
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
  host: <%= ENV['APP_DATABASE_HOST'] %>

そして、接続先になるべきDBの情報は、以下コマンドで確認できる。

heroku config -a rails-docker-diego

出力はこんな感じ

itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % heroku config -a rails-docker-diego
=== rails-docker-diego Config Vars
CLEARDB_DATABASE_URL: mysql://bd71f48521eb76:5dacd1c6@us-cdbr-east-04.cleardb.com/heroku_edab841a62d88d9?reconnect=true
  • mysqlより後のbd71f48521eb76がユーザー名。
  • 5dacd1c6がパスワード
  • us-cdbr-east-04.cleardb.comがホスト名
  • heroku_edab841a62d88d9がDB名である

そして、これを環境変数として設定するコマンドを使う。先ほどdatabese.ymlにて設定した環境変数名に応じて記載する。

heroku config:add APP_DATABASE='heroku_edab841a62d88d9' -a rails-docker-diego

heroku config:add APP_DATABASE_USERNAME='bd71f48521eb76' -a rails-docker-diego

heroku config:add APP_DATABASE_PASSWORD='5dacd1c6' -a rails-docker-diego

heroku config:add APP_DATABASE_HOST='us-cdbr-east-04.cleardb.com' -a rails-docker-diego

確認するには、以下コマンド

heroku config -a rails-docker-diego

Dockerfileを本番用に修正

dockerfileをいじる。
FROMの下に一行記載した後、
末尾に以下を追記する。

FROM ruby:2.7
ENV RAILS_ENV=production

以下略

COPY start.sh /start.sh
RUN chmod 744 /start.sh
CMD ["sh","/start.sh"]
  • start.shをコンテナにコピーする
  • 実行するために、実行権限を変える
  • start.shを実行する
    という処理をしている。

ソースコードで、start.shというシェルスクリプトファイルをdockerfileと同列に作る。

これに、本番環境用の処理を入れる。

#!/bin/sh

if [ "${RAILS_ENV}" = "production"]
then
    bundle exec rails assets:precompile
fi

bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0
  • 一行目はシェルの約束
  • if分の中は、本番環境の時のみ、assets:precompileというものを実行したいという意味の文になっている。Rails特有の処理。本番だと、これを実行する必要がある。
    • dockerファイルは条件分岐が難しいので、それを行うために、シェルのプログラムを入れている。
  • bundle exec rails sで、Railsのサーバーを起動している。環境変数で何も設定されていなければ、3000番を使用する。IPアドレスは、どこからでも受け付けるという設定0.0.0.0

Dockerfileで、分岐をする時は、

  • 今回のようにシェルを使うor
  • Dockerfile.developみたいに、Docker fileを複数作るという手がある。

assets:precompileを実行するために、
以下の環境変数を設定しておく。

heroku config:add RAILS_SERVE_ATATIC_FILES='true' -a rails-docker-diego

のちに必要になる設定を入れる

タイムアウト時間について
https://tools.heroku.support/limits/boot_timeout
以下のリンクにアクセス。

無料だとマシンパワーが少なく、ポートバインド時間を過ぎるとタイムアウトされるという事がよくあるので、タイムアウトの時間を変更する。

ローカルのサーバーを削除する。

ローカルでサーバーが立ち上がっていると、本番用のものとコンフリクトして、起動しなくなる事がある。(Herokuの問題)

docker-compose down 

また、念の為、src/tmp/pids/server.pidというファイルも削除する。これは、downされたら消えるはずだが、これがあるとエラーが起こるので、削除しておく。

rm src/tmp/pids/server.pid

Dockerイメージをビルド&リリース

herokuにイメージをビルドしてリポジトリにアップするには、以下コマンドを使う。

heroku container:push web -a rails-docker-diego

ビルドになるので、結構時間かかると思われる。

ちなみに、こんな感じのエラーが出た。

no basic auth credentials
 !    Error: docker push exited with Error: 1

解決策として、ログインし直すと、正常にできた。

heroku container:login

レジストリにあるイメージをHeroku常にコンテナをリリースしていく。

heroku container:release web -a rails-docker-diego

また、通常だと、DBのマイグレーションの処理を行う。Railsの場合。

  • マイグレーション。データベースの更新の仕組み。テーブルを更新する時に使うコマンド。
heroku run bundle exec rake db:migrate RAILS_ENV=production -a rails-docker-diego

ローカルで実行するには、こんなコマンド。compose up をした後に実行する。

docker-compose exec web bundle exec rake db:migrate

ソースコードを修正したら、イメージを再作成する必要がある。つまり、もう一度pushし直す必要がある。

アプリを開いていく。

heroku open -a rails-docker-diego

ブラウザが開く。今回エラー起きている。環境変数のエラーっぽいけど、やるきおきないので放置。

Yeah! your Rails !!というのは、ローカルの環境でないと動作しない。

エラーがおきたら、ググって調べる?
一つ、環境変数を設定しておきたい。

これを行うと、たくさんログが表示されるようになる。

heroku config:add RAILS_LOG_TO_STDOUT='true' -a rails-docker-diego

そして、これを設定した上で、以下コマンドを打つと、ログが表示される。

heroku logs -t -a rails-docker-diego

機能追加

トップページにアクセスしたら、何か表示されるというものを作っておきたい。

  1. railsのコントローラーを作成する。
docker-compose exec web bundle exec rails g controller users

  1. ソースコードで、ルーティングの設定をみる。routes.rbをみるそして、以下のように変更
    • ルーティング:どのURLに来たら、どこに飛んで、どうアクションするかを記載する。
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html

  get '/', to: 'users#index'
end
  1. コントローラーをみる。app/controllers/users_controller.rbにある。
class UsersController < ApplicationController
    def index
    end
end
  1. viewファイルの作成
    /src/app/views/users/index.html.erb
    を作成する。中身は適当でOK.

これができたら、プッシュとリリースをやってみよう。
その状態で、heroku openとすると、また表示される。再度見てみると、変更されているのではないだろうか。

CI/CDについて

CI・CDをdockerで構築する。

本番環境を構築したのはいいが、直した時にいちいち手動でデプロイするのが面倒。

そこで、ソースコードが修正されたら、自動でデプロイされるようにしたい。

まずは、GitHubにソースコードを共有する。
そして、チームのみんなが同じコードを参照する。

用語

CIとは

継続的なインテグレーション。
ビルド・テストを自動で実行してくれる。
コードの品質を一定に保ってくれる。

CDとは

継続的なデリバリ。
マージされたら、自動でデプロイしてくれる仕組み。

CircleCI

CI/CDをクラウド上で行なってくれるサービス。
UnityであればGameCIのようなもの。
そして、これらを組み合わせた流れはこんな感じ

  1. 作ったコードは、CIでテストされ、GitHubに送られる
  2. GitHubから、CDによってHerokuにデプロイされる

コードをgithubに挙げる

  1. まずは、ブランチ(並行で作業していく時に作るもの。)を作る。
  2. ファイルの修正が終わったら、コミット(ファイルの履歴を保存)をする。
  3. GitHub常に上げるものを、プッシュという。
  4. そしてGitHub上で、チーム開発するために、プルリクエストを行う
  5. それが良ければ、マージ(修正内容を、メインブランチにつなげる)
  6. そして、ローカルのブランチを切り替え、新しいブランチをプルする。

主なコマンド

  • gitリポジトリの作成。このディレクトリ以下を対象にするというコマンド。
git init
  • GithubのURLを登録。リポジトリのURLを登録させる。
git remote add origin <URL>
  • ブランチを作成して切り替える。新しいブランチに切り替える。
git switch -c <ブランチ名>
  • 変更内容をステージングに追加
git add .
  • 変更内容をコミット(addとセットで使う。addされたものをcommitさせるので。)
git commit -m "メッセージ"
  • Githubにプッシュ
git push origin <ブランチ名>
  • ブランチを作成して切り替える。(メインブランチ)
git switch  <ブランチ名>
  • GitHubの変更内容を取り込む
git pull origin <ブランチ名>
  • 変更したファイルを確認
git status
  • 変更したファイル内容の確認
git diff

githubでの流れ

リポジトリ作成

ログインして、new repogitry

  • 名前はアプリ名と揃えておく(わかりやすくするため)
    • rails-docker-diego
  • publicでもprivateでもOK
  • descriptionがいるなら記載

そして、Create repogitoryを押す

Gitでコードを管理する。

リポジトリができたら、コードを管理する。基本的には、ローカルで、真ん中あたりに出てるコードを打ち込むことになる。

git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/itohdaigo/rails-docker-diego.git
git push -u origin main
  1. 今回作ったファイル達が含まれているコードのルートになる所(ここではrails_docker)で、git initを実行する。(ちなみに、2回やるとエラーになる。)
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % ls
Dockerfile		docker-compose.yml	src			start.sh
  1. .gitignoreを追加する。機密情報とかを上げるのは危険。バージョン管理で、いちいちあげたりするものを無視する設定。
    いちおう、元々のsrcの中にもあるが、これは直下でないと意味がない。

    なので、これらを示す2つのファイルを移動させる
mv src/.gitignore .

mv src/.gitattributes .

そして、src直下の.gitignoreなどを削除しておく。(srcの中にいると、二重管理になり、エラーが起こるため。)

rm  -rf src/.gitignore
itoudaiware@itoudaiwarenoMacBook-Pro src % rm -rf .git
  1. git.ignoreを修正する。
# Ignore bundler config.
/.bundle

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/
!/tmp/pids/.keep

こんな感じになっているのを、src直下であるというふうに、指定しなおしていく。全ての設定の所を、srcの下とする。

# Ignore bundler config.
src/.bundle

# Ignore all logfiles and tempfiles.
src/log/*
src/tmp/*
!src/log/.keep
!src/tmp/.keep

# Ignore pidfiles, but keep the directory.
src/tmp/pids/*
!src/tmp/pids/
!src/tmp/pids/.keep

また、追加でsrc/db/mysql_dataも、上のファイルに追記する。ちなみにこれは、バージョン管理する必要がないので、docker-compose.yamlにて、指定している。

  1. ステージングに追加
git add .

この時、src % rm -rf .gitとしないと、

error: 'src/' does not have a commit checked out
fatal: adding files failed

と表示される。
5. コミット&プッシュ

git commit -m "first commit"
  1. ブランチ作成
git branch -M main
  1. リモートリポジトリにアクセス(今回、SSH認証を既にしているので、これでいく。)
git remote add origin git@github.com:itohdaigo/rails-docker-diego.git
  1. プッシュする。
git push -u origin main

これでリロードすると、リポジトリがあるのがわかる。

CIを作る。

流れはこんな感じ。

  1. テストコードを記載
  2. CircleCIに登録
  3. プロジェクトを登録
  4. configを設定
  5. 環境変数を設定
  6. Githubにプッシュ
  7. テストを修正

テストコード記載

実は、既に/src/test/controllers/users_controller_test.rb

に、テストコードがある。
それを改造していく。

まずは、コメントアウトを外し、assert falseとする。

require "test_helper"

class UsersControllerTest < ActionDispatch::IntegrationTest
  # test "the truth" do
  #   assert true
  # end
end

そして、まずDocker-compose up をする。

docker-compose up -d

そして、テストを実行する。bundle exec rake test がテストを実行するコマンド。

docker-compose exec web bundle exec rake test 

エラーで落とされたらOK

Circle CIに登録する。

以下リンクにアクセス
https://circleci.com/ja/

初めてなら、登録から登録を行う。
そして、登録する時は、**GitHubでログインを選ぶ。**そうすると、GitHubと連携してくれる。

プロジェクトを登録する。

対象のリポジトリを選ぶ。そして、これのセットアッププロジェクトを押す。

とりあえず上を選んで進む。

なんか説明と表記が違うけど、まあ、とりあえずこのまま進む。

コンフィグの設定

.circleci の中で、config.ymlを参照することで、CIができるようになる。

  1. RAILS直下に.circleciのフォルダを作る。
  2. その下に、config.ymlを作成する。

orbsは、ジョブを定義しておいて、共有できるもの。
ここでは、buildtestを行うようにしている。一番下のworkflowに定義された順番に処理をおこなっていく。今回は、ビルドして、実行(テストしている。)

  • working_directoryは、GitHubのリポジトリの名前にする。
  • チェックアウトのパスも、リポジトリ名にする。
  • orbsを使うと、install-devsが用いれる。

テストの中身は、

  • rubyとmysqlのイメージを取得している。
  • DATABASEのユーザー名などは、APPTestといった形にしている。
  • APPDATABASEHOSTは、127.0.0.1(自分自身)を設定する。
  • この書式で、db:migrateコマンドを実行するという
      - run:
          name: Database setup
          command: bundle exec rails db:migrate
  • stepの所でも、同じようにコマンドを実行している。
version: 2.1
orbs:
  ruby: circleci/ruby@1.1.2
  heroku: circleci/heroku@1.2.3

jobs:
  build:
    docker:
      - image: circleci/ruby:2.7
    working_directory: ~/rails-docker-dito/src
    steps:
      - checkout:
          path: ~/rails-docker-dito
      - ruby/install-deps

  test:
    docker:
      - image: circleci/ruby:2.7
      - image: circleci/mysql:5.5
        environment:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: app_test
          MYSQL_USER: root
    environment:
      BUNDLE_JOBS: "3"
      BUNDLE_RETRY: "3"
      APP_DATABASE_HOST: "127.0.0.1"
      RAILS_ENV: test
    working_directory: ~/rails-docker-dito/src
    steps:
      - checkout:
          path: ~/rails-docker-dito
      - ruby/install-deps
      - run:
          name: Database setup
          command: bundle exec rails db:migrate
      - run:
          name: test
          command: bundle exec rake test
        
        
  deploy:
    docker:
      - image: circleci/ruby:2.7
    steps:
      - checkout
      - setup_remote_docker:
          version: 19.03.13
      - heroku/install
      - run:
          name: heroku login
          command: heroku container:login
      - run:
          name: push docker image
          command: heroku container:push web -a $HEROKU_APP_NAME
      - run:
          name: release docker image
          command: heroku container:release web -a $HEROKU_APP_NAME
      - run:
          name: database setup
          command: heroku run bundle exec rake db:migrate RAILS_ENV=production -a $HEROKU_APP_NAME

workflows:
  version: 2
  build_test_and_deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: main

また、これとは別に追記する。

test:
  <<: *default
  database: app_test
  host: <%= ENV.fetch("APP_DATABASE_HOST") { 'db' } %>

ここのhostの部分は、環境変数が入っている時は、これを使うが、CircleCIで環境変数を用いている場合、APP_DATABASE_HOSTがない時のみ、dbを使うという処理である。

また、/src/config/master.keyというものは、ネットでばれるとよくないものであるので、ignoreに入っていた。しかし、これをHeroku
にいれたいので、環境変数にする。

heroku config:add RAILS_MASTER_KEY="xxx" -a rails-docker-diego

そして、この変更をGitに上げる。ciの変更分を、masterに変更する。

  1. git switch -c ci
  2. git branch
  3. git add .
  4. git commit -m "circle-ciが動くようにconfigを設定した"
  5. git push origin ci

プッシュしたら、GitHubをみる。

  1. Pull requestを選択
  2. New Pullrequestを選択
  3. そして、baseがmainで、compareをciとする。
  4. これは、ciの変更分を、mainに取り込むという意味である。

そして、Create pull requestを押す。
じつは、pushが始まった瞬間に、CircleCIが動作を行う。
成功すると緑、失敗すると赤になる。

基本的に、テストに落ちるとマージリクエストのボタンが押せなくなる。

users_controller_test.rbのassertをtrueにして、達ようにする。

require "test_helper"

class UsersControllerTest < ActionDispatch::IntegrationTest
   test "the truth" do
     assert true
   end
end

テストが通るか確認。ちなみに、以下だと失敗という意味である。

itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % docker-compose exec web bundle exec ra
ke test
service "web" is not running container #1

ちなみに、今回失敗した例を確認するために、こんなデバッグをした。

  1. コマンドを実行したら、webが動いていないと言われる。
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % docker-compose exec web bundle exec rake db:migrate
service "web" is not running container #1
  1. 動いていないコンテナをみる。docker ps -a今回はwebが動いておらず、DBが動いているのがわかる。
itoudaiware@itoudaiwarenoMacBook-Pro rails_docker % docker ps -a
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                     PORTS                 NAMES
f0265e7affcc   rails_docker_web   "bundle exec rails s…"   48 minutes ago   Exited (1) 5 minutes ago                         rails_docker-web-1
5b844e315934   mysql:8.0          "docker-entrypoint.s…"   52 minutes ago   Up 5 minutes               3306/tcp, 33060/tcp   rails_docker-db-1
129d3336c6fe   254a938785d2       "/bin/sh -c 'curl -s…"   3 days ago       Exited (100) 3 days ago                          distracted_blackburn
  1. 動いてないコンテナのログをみる。docker logs rails_docker-web-1

すると、上の方に、databese.ymlの三十行目に何かあるらしいと書いてある。

=> Booting Puma
=> Rails 6.1.4.1 application starting in production
=> Run `bin/rails server --help` for more startup options
/app/config/database.yml:30:in `block in <main>': Cannot load database configuration: (NameError)
undefined local variable or method `db' for main:Object
Exiting
  1. みると、PP_DATABASE_HOSTになってた。
docker-compose exec web bundle exec rake test

のコマンドを実行して問題なさそうで
通ったなら、gitに変更していく。

  1. git add .
  2. git commit -m "テスト通過した"
  3. git push origin ci

うまくいったコードをローカルにもってくる。

  1. git switch main
  2. git pull origin main

これで、CIの仕組みが完成。

肝は、設定(circle.config)を入れることで、プッシュされる度にテストされる。
ということが実行されるということ。

CDについて

流れはこんな感じ

  1. configを修正
  2. 環境変数を設定
  3. viewファイルの修正
  4. githubにプッシュ
  5. マージ&自動デプロイ

とりあえず、開発用ブランチを作成

git switch -c cd

また、ブランチを削除するには、-dオプションを使う。

git branch -d ci

configの修正

circle.ci/config.yml
を修正する。

orbsに以下を追加する。

heroku: circleci/heroku@1.2.3

さらに、workflowに、jobsを追加する。
メインのbranchに、マージされた時だけ、deployのjobが追加されるという形式である。

 jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: main

setup_dockerをいれると、dockerを使う。

      - setup_remote_docker:
          version: 19.03.13
          

また、runの所にあつのは、実際に打って行った
コマンドである。

      - run:
          name: heroku login
          command: heroku container:login
      - run:
          name: push docker image
          command: heroku container:push web -a $HEROKU_APP_NAME
      - run:

環境変数の設定

こんな感じに、環境変数を入れ込む処理を行なっているので、circlre.ciに、環境変数を入れる処理が必要。

      - run:
          name: push docker image
          command: heroku container:push web -a $HEROKU_APP_NAME
  1. circleciにアクセス

  2. projectから、自分のアプリ(rails-docker-diego)を選択

  3. その中のproject settingに、Environment variableがある。

  4. ADDしていく。

もう一個、HEROKU_API_KEYというのを設定する。
これは、HEROKUにログインしてから、AccountSettingsの中の、下の方にあるAPIKeyをみる。これをコピーして、貼り付ける。

viewファイルの修正を行う。

src/app/views/users/index.html
のファイルをみる。
修正されたのが分かるように、一部を変える。

<h1> sample ß </h1>
を、いかに修正

<h1> sample ß !!</h1>

docker-compose upで、ローカルで試してみるのも良いだろう。

Githubにプッシュする。

git add .

git commit -m "cd用設定を追加"

git push origin cd

pushしたら、GitHubを確認。
先ほどと同じように、cdのプルリクエストが行えるようになっているので、押す。

baseがmainで、compareがcdになっているのを確認し、プルリクエストを押す。

そして、うまくいったら、こんな感じで緑色で表現される。

ちなみに、:の後にスペースがない場合、そこでうまくいかなくなったりする。

そして、マージプルリクエストを押す。
そして、Confirm Mergeを押す。
ついでに、古いブランチも消しとくDELETE branch

デプロイされているか確認

circlrciのWebの画面をみてみると、現在デプロイ中である。

これがうまくいけば、緑のチェックがつくハズである。

今回、このようにエラーがでたので、deploy部分のymlを修正する。

deploy:
docker:
- image: circleci/ruby:2.7.4
ソースコードを変えずに、環境変数のみ追加等をする場合、循環するマークを押せば、もう一度ビルドとテスト、デプロイもシテくれる。

デプロイが問題なく実行されたら、

heroku open -a rails-docker-diego 

とする。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1