- 投稿日:2020-09-07T18:53:17+09:00
Rails on Dockerの環境構築手順
環境
- MacOS Catalina 10.15.6
- Docker 2.3.0.3
- Ruby 2.7.1
- Rails 6.0.3.2
- Bundler 2.1.4
- Gem 3.1.2
- Yarn 1.22.5
手順
予めDockerをインストールしておいて下さい。
Rubyイメージの取得
$ docker pull ruby
Dockerコンテナを起動
<NAME>
と<DIRECTORY>
は適時変更して下さい。$ docker run -i -t --name <NAME> -p 3000:3000 -v "$PWD":<DIRECTORY> /bin/bashRailsの導入
作業ディレクトリへ移動します。
$ cd <DIRECTORY>次に、
Gemfile
の生成$ bundle init
生成されていることを確認。
$ ls Gemfile編集用に
vim
をインストール。
(ホストPCのディレクトリから直接編集してもOK)$ apt-get install vim-tiny編集します。
# gem "rails"
のコメントアウト#
を外します。$ vim.tiny Gemfile
編集後# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails"Gemをインストール。
$ bundle install新規Railsプロジェクトの作成。
$ bundle exec rails new .NodeJSをインストール。
$ apt-get install nodejsWebpackerをインストールしますが、その前に
Yarn
が必要なのでインストールします。
しかし、そのままapt-get install
すると0.32+git
というバージョンでインストールされてしまい、
webpack:install
した際に行われるyarn
のバージョンチェック時にエラーが出てしまうようです。
参考文献: 【Rails】ArgumentError: Malformed version number string 0.32+gitでwebpacker:installが実行できない場合の対処方法$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - $ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list $ apt-get update && apt-get install yarnWebpackerをインストール。
rails webpacker:installRails Server起動
起動できるはずです。
$ bundle exec rails server自分の環境の場合、うまくローカルで接続できなかったので明示的に指定すると無事接続できました。
$ bundle exec rails server -b 0.0.0.0=> Booting Puma => Rails 6.0.3.2 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode... * Version 4.3.6 (ruby 2.7.1-p83), codename: Mysterious Traveller * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://0.0.0.0:3000 Use Ctrl-C to stop Started GET "/" for 172.17.0.1 at 2020-09-07 09:47:16 +0000 Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1 (1.5ms) SELECT sqlite_version(*) Processing by Rails::WelcomeController#index as HTML Rendering /usr/local/bundle/gems/railties-6.0.3.2/lib/rails/templates/rails/welcome/index.html.erb Rendered /usr/local/bundle/gems/railties-6.0.3.2/lib/rails/templates/rails/welcome/index.html.erb (Duration: 6.3ms | Allocations: 295) Completed 200 OK in 21ms (Views: 12.1ms | ActiveRecord: 0.0ms | Allocations: 1651)Yay! You're on Rails!
おわり
参考文献: 知識0から始めるRails on Docker
- 投稿日:2020-09-07T18:28:49+09:00
【AWS ECS】Fargateの「コマンドの上書き」
はじめに
ECSで起動タイプFargateのタスクを実行する際の「コマンドの上書き」という項目について、「実行時パラメータを渡せるようなものかな」と思って使おうとしました。
この理解でざっくり正解と言えますが、正しく使うにはdockerのENTRYPOINT、CMDコマンドの知識が必要で、自分のようにdockerを使いこなす前にFargateを使おうとした人にとってはハマりどころかと思います。
これらについて調べた内容を記載しています。コマンドの上書き
ECSタスクの実行やタスクスケジュールの設定画面で「コンテナの上書き」という項目があり、ここで設定した内容をECSタスクに設定したコンテナ実行時に利用することができます。
「コンテナの上書き」の中に「コマンドの上書き」というフリー記述項目があります。
画面上のヒントメッセージに「コンテナに渡すCMD」とありますが、どういうことか次項で説明します。dockerのENTRYPOINTとCMD
dockerfileで「ENTRYPOINT」と「CMD」という命令があり、どちらもコンテナ実行時(docker run時)に実行されるコマンドです。
「コマンドの上書き」の挙動を理解するためにこれらの理解が必要となります。この2つは、コンテナ実行時に渡されるパラメータの扱いが異なります。
ENTRYPOINTはdocker runのパラメータをそのままENTRYPOINTのパラメータとして扱います。
CMDはdocker runのパラメータをCMD自体として扱います。(CMDの上書き)ENTRYPOINT
コンテナ実行時に必ず実行されるコマンドと引数(省略可)を設定します。
[書式]ENTRYPOINT ["実行可能なもの", "パラメータ1", "パラメータ2"][例]
ENTRYPOINT ["ping", "localhost"] →pingコマンドにlocalhostという引数を渡して実行CMD
コンテナ実行時のデフォルト実行コマンドと引数を設定します。
[書式]CMD ["実行バイナリ", "パラメータ1", "パラメータ2"][例]
CMD ["ping", "localhost"] →pingコマンドにlocalhostという引数を渡して実行併用
ENTRYPOINTとCMDを併用する場合、CMDにはENTRYPOINTに渡すパラメータを設定します。
[書式]ENTRYPOINT ["実行可能なもの", "パラメータ1", "パラメータ2"] CMD ["パラメータ3", "パラメータ4"][例]
以下の2例はどちらも同じコマンドが実行されるENTRYPOINT [“ping”] CMD[“-c”,”4”,“localhost”] →ping -c 4 localhost になるENTRYPOINT [“ping”,”-c”] CMD[”4”,“localhost”] →ping -c 4 localhost になる実行時(docker run時)のパラメータ
docker run実行時に指定したパラメータはコンテナ定義のCMDとしてコンテナに渡され、コンテナ起動時にはこのCMDが採用されます。(CMDの上書き)
前項の「コマンドの上書き」はこの仕様に相当します。[書式]
docker run <コンテナ指定> パラメータ1 パラメータ2[例]
コンテナ定義に「ENTRYPOINT [“ping”,”localhost”]」の設定がある場合、ENTRYPOINT + CMDの併用となるdocker run <コンテナ> -c 4 →ping localhost -c 4 になるコンテナ定義に「CMD [“ping”,”localhost”]」の設定がある場合、CMDを上書きとなる
docker run <コンテナ> echo hoge →pingは実行されず、echo hogeが実行されるコンテナ定義に「ENTRYPOINT [“ping”,”localhost”]」と「CMD [“-c”,”4”]」の設定がある場合、CMDを上書きとなる
docker run <コンテナ> -c 10 →ping localhost -c 10 になる動作確認
前項での実行時パラメータの仕様通りに動くか、「コマンドの上書き」の動作確認をします。
ENTRYPOINTを設定したもの、CMDを設定したもの、両方設定したもの、の3つのコンテナ定義を作成し、それぞれコマンドの上書きなし・ありで実行した場合の系6パターンの出力を確認します。テスト用ファイル
test_script.shを作成。シェルに渡された引数をechoする。
#!/bin/sh # 引数の数をecho echo arg length is $# # 渡された引数を全てecho for x do echo arg is "$x" doneコンテナ定義
[ENTRYPOINTを設定したもの]
FROM ubuntu COPY . . RUN chmod 777 test_script.sh ENTRYPOINT ["sh", "test_script.sh", "ENTRYPOINT"][CMDを設定したもの]
FROM ubuntu COPY . . RUN chmod 777 test_script.sh CMD ["sh", "test_script.sh", "CMD"][両方設定したもの]
FROM ubuntu COPY . . RUN chmod 777 test_script.sh ENTRYPOINT ["sh", "test_script.sh"] CMD ["BOTH"]テスト実行
ENTRYPOINT
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・コマンド上書きありなしどちらでも、arg is ENTRYPOINTが必ず出力されている
→ENTRYPOINTは必ず実行される
・コマンドの上書きを設定した場合、arg is override1, arg is override2が出力されている
→ENTRYPOINTにパラメータを渡すCMDとして処理されるCMD
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・arg is CMDはコマンド上書き時に出力されない
→コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される両方設定したもの
[コマンドの上書きなし]
[コマンドの上書きあり]
[結果]
・test_script.shのecho処理が実行されている
→ENTRYPOINTは必ず実行される
・arg is BOTHはコマンド上書き時に出力されない
→コンテナ定義のCMDは無視され、コマンドの上書きの内容がCMDとして処理される調査結果
こちらで述べたように、Fargateの「コマンドの上書き」はコンテナ実行時にCMDとして渡されるものでした。
コンソールでの「コンテナに渡すCMD」というヒントメッセージがそのまま正解ですね。所感としては、「コマンド」というワードがここではdockerの用語の「CMD」を表しているようで、自分はこの点が少しわかりにくさを感じました。
(英語表記でも「Command」のようです)
使うのにdocker知識が前提に感じるので、どうせなら「CMDの上書き」の方がわかりやすい気がします。注意点
ECSの開発者ガイドで、コンテナ定義にENTRYPOINTがある場合とない場合の「コマンドの上書き」の設定について記載されていますが、誤解しそうな表現になっていると思います。
[ENTRYPOINTがない場合の説明]If your container definition does not specify an ENTRYPOINT, the format should be a comma-separated list of non-quoted strings. For example:
/bin/sh,-c,echo,$DATE[ENTRYPOINTがある場合の説明]
If your container definition does specify an ENTRYPOINT (such as sh,-c), the format should be an unquoted string, which is surrounded with double quotes and passed as an argument to the ENTRYPOINT command. For example:
while true; do echo $DATE > /var/www/html/index.html; sleep 1; done「ENTRYPOINTがない場合はカンマ区切り」という点と、ENTRYPOINTがある場合のサンプルから、「ENTRYPOINTがある場合はカンマ区切り指定ではない」と自分には見えましたが、動作確認で実証したようにENTRYPOINTがあってもカンマ区切り指定可能でした。
参考
ECSの開発者ガイド
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs_run_task_fargate.htmlDockerfile リファレンス
http://docs.docker.jp/v1.11/engine/reference/builder.htmlENTRYPOINTは「必ず実行」、CMDは「(デフォルトの)引数」
https://pocketstudio.net/2020/01/31/cmd-and-entrypoint/
- 投稿日:2020-09-07T17:17:26+09:00
【GCP】Cloud BuildでCI/CDパイプラインを構築する。
はじめに
Cloud BuildはGCP上でCI/CDを行うためのサービスです。
特にコンテナを扱ったソリューションと相性がよく、
テストやビルドはGCP上にプロビジョニングされたコンテナ内で行われ、
Cloud FunctionsやCloud Runといった様々なコンピューティングサービス上にデプロイすることができます。本記事では、
- ソースコードの管理:Cloud Source Repositories
- テスト及びビルド:Cloud Build
- コンテナレジストリ:Container Registry
- デプロイ:Cloud Run
の全てGCP内で完結するリソースを使ってコンテナアプリケーションにおけるCI/CD環境を構築したいと思います!
本記事で使用したソースコードは、こちらにあります。開発環境
- macOS Catalina 10.15.6
- Docker Desktop stable 2.3.0.4
- Google Cloud SDK 308.0
登場人物たち
Cloud Source Repositories
プライベートなGitリポジトリをホスティングできるサービスです。
https://cloud.google.com/source-repositories/docs?hl=jaContainer Registry
プライベートなDockerイメージをホスティングできるサービスです。
https://cloud.google.com/container-registry/docs?hl=jaCloud Run
マネージドなコンテナ実行プラットフォームです。
コンテナを手軽にサービスとしてデプロイ、公開可能です。
https://cloud.google.com/run/docs?hl=jaCloud Build
本記事の主役です。
冒頭にもあるように、マネージドなCI/CD環境を構築できます。
詳しくは後の項で説明しますが、ビルドコンテナ内でgcloudコマンド叩けたりと柔軟なシナリオが作成可能です。
https://cloud.google.com/cloud-build/docs?hl=ja作ってみよう!
ローカルにGitリポジトリを作成
適当な空のディレクトリを作成し、
git init
を行います。$ mkdir cloudbuild-sample && cd cloudbuild-sample $ git initサンプルアプリケーションの作成
Cloud Runにデプロイするアプリケーションを作成します。
AとBの和を返す簡単なアプリを考えます。$ mkdir workspacecloudbuild-sample/workspace/go.modmodule mymod go 1.15cloudbuild-sample/workspace/main.gopackage main import ( "encoding/json" "fmt" "log" "mymod/utils" "net/http" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { j := json.NewDecoder(r.Body) var req struct { A int `json:"a"` B int `json:"b"` } j.Decode(&req) fmt.Fprintf(w, "%d\n", utils.Add(req.A, req.B)) }) log.Println("start server...") http.ListenAndServe(":8080", mux) }足し算の関数を定義するサブパッケージを作成します。
$ mkdir workspace/utilscloudbuild-sample/workspace/utils/add.gopackage utils // Add return a + b func Add(a int, b int) int { return a + b }cloudbuild-sample/workspace/utils/add_test.gopackage utils import "testing" func TestSuccessAdd(t *testing.T) { expect := 3 result := Add(2, 1) if expect != result { t.Fatalf("result is expected %d, got %d ", expect, result) } } func TestFailureAdd(t *testing.T) { t.Fatal("FAILURE!!") }CI実行時にテストの失敗を考慮されるかを確認するため、意図的に失敗するテストコードを作成しました。
さらに、公開用のDockerイメージファイルも作成します。
cloudbuild-sample/DockerfileFROM golang:1.15-alpine as builder WORKDIR /opt/build COPY go.* ./ RUN go mod download COPY . ./ RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o app FROM alpine:3.12 ENV PORT 8080 COPY --from=builder /opt/build/app /opt/app WORKDIR /opt CMD ["./app"]お疲れ様です!
上記のアプリは、$ curl -X POST -H "Content-Type: application/json" -d '{"a":41, "b":10}' http://localhost:8080 51のようなリクエストに対して、aとbの和を返してくれます。
gcloudコマンドの下準備
前提として、既にGCPプロジェクトが作成済みでgcloudコマンドが使用できることを確認してください。
ここではパイプライン環境構築のためのGCPプロジェクト側での設定を行います。まずは利用するサービスのAPIを有効化しましょう!
$ gcloud services enable sourcerepo.googleapis.com \ run.googleapis.com \ cloudbuild.googleapis.com \ containerregistry.googleapis.com次にSource Repositoriesにリポジトリを作成し、リモートにセットします。
$ gcloud source repos create cloudbuild-sample $ git remote add google https://source.developers.google.com/p/{YOUR_PROJECT_ID}/r/cloudbuild-sampleさらにリポジトリに対し認証情報を付与します。
$ git config --local credential.https://source.developers.google.com.helper gcloud.shここまでのコードをpushできるか確認してましょう。
$ git add . $ git commit -m 'first commit' $ git push google master次にCloud Buildのサービスアカウントに対しCloud Runへデプロイするための役割を付与します。
$ gcloud projects add-iam-policy-binding {YOUR_PROJECT_ID} \ --member serviceAccount:{YOUR_PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \ --role roles/run.admin $ gcloud projects add-iam-policy-binding {YOUR_PROJECT_ID} \ --member serviceAccount:{YOUR_PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \ --role roles/iam.serviceAccountUserお疲れ様です!
これで下準備は完了です。Cloud Buildの構成ファイルを作成する。
Cloud Buildではテストやビルドの手順をYAMLファイルとして定義します。
簡単な例として、前項で作成したサンプルアプリケーションのテストを実行し、
成功したらデプロイ用のイメージをビルドする手順書を作成してみます。cloudbuild-sample/cloudbuild.yamlsteps: # steps下にテスト〜デプロイまでの各手順を定義します。 - name: 'golang:1.15-alpine' # コマンドを実行するコンテナイメージ id: 'do testing' # 各ステップを表す識別子 entrypoint: '/bin/sh' # コンテナが実行される際のエントリーポイント env: # コンテナが実行される際に渡される環境変数 - 'CGO_ENABLED=0' dir: 'workspace' # エントリーポイントが実行されるディレクトリ args: # エントリーポイントに対する引数 - '-c' - | go mod download \ && go test mymod/... - name: 'gcr.io/cloud-builders/docker' # 注1 id: 'do building' args: # エントリーポイントは docker です。 - 'build' - '-t' - 'gcr.io/$PROJECT_ID/sample_app:$SHORT_SHA' # 注2 - '-f' - './Dockerfile' - './workspace'設定しているオプションをよく見てみると、
普段のdocker run
コマンドを構成するオプションと似ていることが確認できるかと思います。注1
nameオプションに設定できるコンテナイメージですが、
クラウドビルダーと呼ばれるGCP側で用意された特別なコンテナイメージも利用可能です。
クラウドビルダーコンテナにはIAM等が適切に割り当てられた環境でgcloud
コマンド等が実行できるため、
柔軟なパイプラインを作成することが可能になります。
利用可能なクラウドビルダーについては
https://cloud.google.com/cloud-build/docs/cloud-builders?hl=ja
を確認してみてください。注2
$PROJECT_ID
や$SHORT_SHA
といった、いくつかの変数はCloud Build側で適切な値に自動で置換されます。
今回の例で使用した
$PROJECT_ID
は、GCPプロジェクトのID
$SHORT_SHA
は、ビルドをトリガーしたリポジトリへのコミットID
です。
変数値の置換については、
https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values?hl=ja
を確認してみてください。それでは完全なCloud Buildの構成ファイルを作成してみましょう!
下記の構成ファイルでは、
go test
を実行しテストが全てパスされるかを確認- デプロイ用のコンテナイメージをビルド
- ビルドされたコンテナイメージをGCRへpush
- GCRへプッシュされたイメージを使い、Cloud Runへサービスをデプロイ
を行います。
cloudbuild-sample/cloudbuild.yamlsteps: - name: 'golang:1.15-alpine' id: 'do testing' entrypoint: '/bin/sh' env: - 'CGO_ENABLED=0' dir: 'workspace' args: - '-c' - | go mod download \ && go test mymod/... - name: 'gcr.io/cloud-builders/docker' id: 'do building' args: - 'build' - '-t' - 'gcr.io/$PROJECT_ID/sample_app:$SHORT_SHA' - '-f' - './Dockerfile' - './workspace' - name: 'gcr.io/cloud-builders/docker' id: 'do pushing image' args: - 'push' - 'gcr.io/$PROJECT_ID/sample_app:$SHORT_SHA' - name: 'gcr.io/cloud-builders/gcloud' id: 'do deploying' args: - 'run' - 'deploy' - 'sample-app' - '--image=gcr.io/$PROJECT_ID/sample_app:$SHORT_SHA' - '--region=asia-northeast1' - '--platform=managed' - '--allow-unauthenticated'お疲れ様です!
パプリックなコンテナイメージとクラウドビルダーを使い分け様々なシナリオに対応できることが実感できたかと思います。
構成ファイルに関する正確な情報はこちらをご確認ください。
https://cloud.google.com/cloud-build/docs/build-config?hl=jaSource Repositoriesへのpushでビルドをトリガーする。
最後に、Source Repositoriesへコードがプッシュされたときに自動的にCloud Buildが走るようトリガーを設定します。
$ gcloud beta builds triggers create cloud-source-repositories \ --repo cloudbuild-sample \ --branch-pattern="master" \ --build-config cloudbuild.yamlcloudbuild-sampleリポジトリのmasterブランチにコードがpushされた際に、
cloudbuild.yamlに定義された内容のパイプラインが実行されます。お疲れ様です!
作業は以上となります。
それではビルドの様子を確認していきたいと思います。ビルドを実行してみよう!
これまでの内容をpushし、Cloud Buildが実行されるか確認してみます。
$ git add . $ git commit -m 'second commit' $ git push google master下記のURLからビルドの履歴を確認できます。
https://console.cloud.google.com/cloud-build/builds?hl=ja今回のビルドでは
go test
に失敗し、ビルドが途中で中断されていることが確認できるかと思います。テストコードを修正し、もう一度ビルドを実行しましょう。
cloudbuild-sample/workspace/utils/add_test.gopackage utils import "testing" func TestSuccessAdd(t *testing.T) { expect := 3 result := Add(2, 1) if expect != result { t.Fatalf("result is expected %d, got %d ", expect, result) } } func TestFailureAdd(t *testing.T) { // t.Fatal("FAILURE!!") # コメントアウトしました。 }再びpushします。
$ git add . $ git commit -m 'fix test code' $ git push google masterビルドが正常に完了したことを確認します。
https://console.cloud.google.com/cloud-build/builds?hl=jaさらに、正常にCloud Runへデプロイされたかを確認しましょう!
https://console.cloud.google.com/run?hl=jaサービスのURLを確認し、curlを叩いてみます。
$ curl -X POST -H "Content-Type: application/json" -d '{"a":41, "b":10}' YOUR_CLOUD_RUN_URL 51お疲れ様でした!
終わりに
本記事ではCloud Buildを使ってGo言語アプリケーションのCI/CDパイプラインを構築しました。
テストやビルドには様々なコンテナイメージを使えるためGo言語に限らず、柔軟なパイプラインを構築できるかと思います!
ありがとうございました!
- 投稿日:2020-09-07T16:32:25+09:00
【Docker】Nginxのconfで環境変数を使う
Rails&pumaで、開発と本番の両方の環境でSSL化をしたくなることがあると思います。
私の場合、ローカルは自己証明書、本番は認証局で登録されている正式な証明書を使いSSL化をしようかなと考えていました。そのためにはNginxのconfファイルに記載する各証明書のパスは開発と本番では別になるため、その部分だけ環境変数で使い分けをしようということになりました。
その時に行った実装手順をメモします。前提
やり方は、環境変数名を記載したファイルから、環境変数に代入した値に変換されたファイルを生成するenvsubstというコマンドを使用します。
実装手順
環境変数は
${SSL_CERTIFICATE_PATH}
のように記述する。
※下記のファイルでは、${SSL_CERTIFICATE_PATH}
と${SSL_CERTIFICATE_KEY_PATH}
の2つを記述しています。docker/nginx/default.conf.templateupstream app { server unix:///app/tmp/sockets/puma.sock; } server { listen 80; server_name _; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name localhost; ssl_certificate ${SSL_CERTIFICATE_PATH}; # 環境変数 ssl_certificate_key ${SSL_CERTIFICATE_KEY_PATH}; # 環境変数 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; root /app/public; location / { proxy_pass http://app; proxy_set_header X-Real-IP $remote_addr; index index.html index.htm; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; } client_max_body_size 100m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; try_files $uri/index.html $uri @app; keepalive_timeout 5; }Dockerfileにて、default.conf.templateを配置する。
DockerfileFROM nginx:1.16 RUN apt-get update && \ apt-get install -y apt-utils \ locales && \ echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \ locale-gen ja_JP.UTF-8 ENV LC_ALL ja_JP.UTF-8 # 初期状態の設定ファイル ADD ./docker/nginx/nginx.conf /etc/nginx/nginx.conf ADD ./docker/nginx/default.conf.template /etc/nginx/conf.d/default.conf.template変換する環境変数をnginxサービスのcommandキーのように指定し、envsubstを動くようにする。
環境変数に代入する値はenvironmentキーで設定する。docker-compose.ymlversion: '2' services: app: # ・・・省略 db: # ・・・省略 nginx: build: context: . dockerfile: ./docker/nginx/Dockerfile ports: - '80:80' - '443:443' volumes: - sockets:/app/tmp/sockets - ./docker/nginx/ssl:/etc/nginx/ssl depends_on: - app command: /bin/sh -c "envsubst '$$SSL_CERTIFICATE_PATH $$SSL_CERTIFICATE_KEY_PATH'< /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" environment: SSL_CERTIFICATE_PATH: /etc/nginx/ssl/server.crt SSL_CERTIFICATE_KEY_PATH: /etc/nginx/ssl/server.key # ・・・省略下記のコマンドでコンテナを立ち上げる時、envsubstコマンドが実行され、環境変数名を記載したファイル(default.conf.template)から、環境変数に代入した値に変換されたファイル(default.conf)が生成されました。
$ docker-compose up -d参考
envsubstを使ってDockerで設定ファイルに環境変数を埋め込めこむ汎用的なパターン - Qiita
さいごに
パスとファイル名さえ間違えなければ躓くことは無いのではないかと思います。
本番環境でもうまくいくようにこれから試してみます。
- 投稿日:2020-09-07T15:16:32+09:00
WindowsのDockerコンテナ上でmatplotlibを動作させる
はじめに
WindowsのDockerコンテナ上でmatplotlibを動作させる方法について記載します。
Windowsは、Windows 10 Pro 64Bit バージョン2004で試しました。これより古いバージョンでも試しました。
Docker Desktopは、WSL2に対応させても以前のままでもどちらも大丈夫です。
Dockerコンテナ内なので、そのままだとmatplotlib等のグラフはホスト側に表示されません。
ホスト側(Windows側)のディスプレイに表示させるようにするには、コンテナOSはlinux系だと思いますので、XServerをWindows側に立ち上げて、そのXServerに表示を流し込むようにする必要があります。VcXsrvをインストール
まず、VcXsrvをインストールします。
インストールが終わったら、WindowsメニューからVcXsrvにあるXLaunchをクリックします。
デフォルトの設定のままでいけます。Firewallの設定は不要のはずです。
また、同じPCで実行するなら不要なはずですが、認証等でエラーになるのであれば下記を試してみてください。
C:\Program Files\VcXsrvなどにある
X0.hostsというファイルを開いてホストのIPアドレスまたはホスト名を追記します。
このファイルは権限がないと編集できないので、プロパティ等で権限追加などを行ってください。
(ちなみに、VS Codeで開くと編集できます)起動すると、画面右下にVcXsrv X Serverのアイコンが表示されるはずです。
そのアイコンを右クリックして表示されるメニューからApplicationsのxclockを選ぶと下記のようにxclockが起動するはずです!
docker-compose.yml
ディスプレイの設定として、docker-compose.ymlに下記を追加します。
docker-compose.ymlenvironment: DISPLAY: host.docker.internal:0.0日本語表示
日本語表示が必要であれば、Dockerfileに以下を追記してください。
fonts-ipafontとしていますが、もちろん別のフォントでも構いません。RUN apt-get update && apt-get install -y fonts-ipafont動作させたプログラム
動作させたプログラムとしてはこんな感じです。
test.pyimport numpy as np import matplotlib.pyplot as plt x = np.arange(-3, 3, 0.1) y = np.sin(x) fig = plt.plot(x, y) plt.show()matplotlib
Docker内で上記プログラムを実行すると下記のようなグラフが表示されます。
おわりに
うまくグラフが表示されましたでしょうか!?
以上ですが、皆様の開発効率向上に寄与できれば幸いです。
- 投稿日:2020-09-07T13:41:01+09:00
【技術書まとめ】『Docker/Kubernetes 実践コンテナ開発入門』を読んだまとめ
第1章 Dockerの基礎
- 構成ファイルとコマンドだけで環境が作れる。
- アプリケーションと実行環境を同梱したデプロイがDocker流
- Dockerを利用するメリット
- 環境起因のトラブルを最小限にできる
- 冪等性が保てる
- いつなんど実行しても同じ結果が保証される
- Docker Compose
- yamlファイルで起動順を制御したりできる
第2章 Dockerコンテナのデプロイ
- Dockerイメージとは
- コンテナを具現化するためのテンプレート
$ docker image pull gihyodocker/echo:latest # イメージを取ってくる $ docker container run -t -p 9000:8080 # コンテナ実行 $ curl http://localhost:9000/ # アクセスしてみる $ docker stop $(docker container ls -q) # 停止 $ docker container stop $(docker container ls --filter "ancestor=example/echo" -q) # 停止 $ docker image build -t example/echo:latest . # dockerイメージを作成 $ docker image ls # dockerイメージを確認 $ docker container run -p 9000:8080 example/echo:latest # ポートフォワーディング
- Dockerに対する操作
- イメージとコンテナの2つに大別される。
Dockerイメージ
- 「Dockerイメージをビルドする」
$ docker image --help # ヘルプを見る $ docker search --limit 5 mysql # 検索する
- imaegeIDはバージョン番号としての役割もある
latest
はGitでいうこところのmaster
ブランチ$ docker image tag example/echo:latest example/echo:0.1.0 # 特定地点をバージョン名などでタグ付けしておくDockerコンテナ
- 実行・停止・破棄の3つの状態
$ docker container run -t -d --name gihyo-echo example/echo:latest # 名前付きコンテナをつくる(開発時に便利) $ docker container run -it alpine:latest # ターミナルが表示されて文字が入力できる。仮想環境にログインしたように使える。 $ docker container ls -q # コンテナIDだけ抽出する $ docker container ls --filter "name=echo1" # 名前でフィルターする $ docker container ls -a # 終了したコンテナを含める $ docker container rm f66f6f2013da # コンテナを破棄する $ echo '{"version":100}' | docker container run -i --rm gihyodocker/jq:1.5 '.version' # そのときだけ必要なコンテナは --rm で即時破棄する $ docker container logs -f &(docker container ls --filter "ancestor=jenkins" -q) # ログを見る $ $ docker container exec -it echo sh # コンテナ内でコマンド実行する $ docker container cp echo:/echo/main.go . # コンテナ内のものをコピーしてくる $ docker container cp dummy.txt echo:/tmp # コンテナへコピーする運用管理向けコマンド
- prune
- 実行していないコンテナを一括削除
$ docker container prune # 実行していないコンテナを一括削除 $ docker image prune # 実行していないイメージを一括削除 $ docker container stats # コンテナ単位でのリソース使用状況を見る
- Docker Compose
- docker同士を連携する
- Jenkinsの例
docker-compose.ymlversion: "3" services: echo: image: example/echo:latest ports: - 9000:8080$ docker-compose up -d # 起動 $ docker-compose down # 停止 $ docker-compose up -d --build # 毎回ビルドして裏で起動 $ docker-compose ps # 起動を確認
volume
はコピーでなく共有する第3章 実用的なコンテナの構築とデプロイ
- Dockerはアプリケーションとインフラをコンテナ単位で分離したもの
- 1コンテナに1つの関心事
- 「1分置きにHello!を出力する」など
- レプリカとして複製された場合に副作用がないか
- Dockerのポータビリティの限界
- CPUアーキテクチャやOSの前提
- ダイナミックリンクの課題
- アプリケーションの挙動を環境変数で制御する
第4章 実践的なアプリケーション構築
SwarmでTODOアプリをつくる
$ docker container run -v ${PWD}:/root ch04/tododb:latestとりあえずここまで。
- 投稿日:2020-09-07T11:23:53+09:00
LaravelをDockerで開発している際におこるPermission Deniedを回避する
LaradockではなくLaravelをDockerでローカル開発している際にPermission Deniedで
/storage/logs
の書き込みが失敗する事象が見られた。
この際の回避方法を残しておきます。おそらくPermission Deniedになる原因はホストとクライアントとでUID、GIDが異なることで発生する。
docker-composeにより構成はNginx > php-fpmとしている場合以下のようにphp-fpm側のDockerfileにNginxのユーザーであるwww-data
に対して任意のUID、GIDが指定できるようにしておく。DockerfileARG PUID=1000 ARG PGID=1000 RUN echo "-> $PUID" RUN echo "-> $PGID" RUN groupmod -o -g $PGID www-data && \ usermod -o -u $PUID -g www-data www-dataこれを
docker-compose build
時に自身のMacのUID、GIDをを差し込む。$ docker-compose build --build-arg PUID=$(id -u) --build-arg PGID=$(id -g) appこれで無事ホストとクライアントのUID、GIDが同じになった。
おまけ
Makefileで上記のコマンドを設定していると
$(id -u)
が正しく解決できなかった。
以下のように書くとうまくいくMakefilebuild_app: $(eval UID := $(shell id -u)) $(eval GID := $(shell id -g)) @docker-compose build --build-arg PUID=$(UID) --build-arg PGID=$(GID) app
- 投稿日:2020-09-07T10:50:14+09:00
DockerでMySQLを5.7から8.0にアップデートする
これはなに
DockerのMySQLを5.7から8.0にアップデートする方法です。
docker composeを使ってる前提です。手順
docker/mysql/Dockerfile- FROM mysql:5.7 + FROM mysql:8.0
docker/mysql/Dockerfile
のバージョンを書き換えます。docker-compose build mysql
docker-compose build
するとバージョンアップされます。
ダメそうなら
docker-compose build --no-cache mysql
で試してみてください。再度mysqlコンテナを起動すると、自動でデータのアップグレードが行われ、MySQL8.0として使えるようになります。
一度データがアップグレードされてしまうと、過去のバージョンのMySQLでは動作しなくなってしまう可能性があるので注意してください。Laravelで発生する問題の解消
mysql8からデフォルトの
auth plugin
が変更になっていて
それにlaravelが対応していなく以下のエラーが発生します。SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from `users` whereそこで、以下の設定を
my.conf
に設定します。my.confdefault-authentication-plugin = mysql_native_password以上、 参考になりましたら幸いです。