docker-compose で複数環境を構築するときの設定をなるべく DRY に書く
概要
docker-compose
の-f, --file
オプションを複数使って、共通の Composeファイル と環境ごとの Compose ファイルを読み込むようにします- こうすることで、共通の設定を DRY に書けます
-p, --project-name
オプションとnetworks
で環境を分離します- 以下のリファレンスの内容が理解できていればこの記事を読まなくても大丈夫です
背景
docker-compose, 便利ですよね。 Docker 完全に理解した *1 くらいのレベルで複数コンテナの環境を作るなら手軽でよいです。
その docker-compose が開発環境だけならまだいいんですが、 テスト用の環境も同じ仕組みで作るようになると、 環境差分をどうするかが課題になります。 例えば、以下のような環境差分が考えられます。
まだまだありそうです。 実際に差分が発生するかはアプリケーションの設計や環境にもよるんですが、 いったんこういう差分があり得るという前提で話を進めます。
アンチパターン
1. Compose ファイルは 1 つで、環境ごとに branch を切る
- 修羅の道です
- Compose ファイルがブランチごとに成長して、目も当てられなくなります
- 唯一のメリットは、「環境ごとの起動コマンドが一緒」
- でも各環境にそれぞれ 1 step で起動できるジョブを用意しておけばいいですよね?
2. 環境ごとに Compose ファイルを作る
- 修羅の道パート 2 です
- やっぱり Compose ファイルがファイルごとに成長していきます
- プロジェクト名が同じだから同じサービス名が使えなくなり、かなりつらいです
解決策
$ docker-compose -f docker-compose.yml -f <your_env>.yml -p <your_env> up -d
実装例はこちら。
解説
-f, --file オプション
共通の Compose ファイル ( docker-compose.yml
) と環境依存の Compose ファイル ( <your_env>.yml
) を読み込みます
共通
$ cat docker-compose.yml version: "3.5" services: web: build: context: ./web volumes: - ./web/proxy-to-back.conf:/etc/nginx/conf.d/proxy-to-back.conf:ro environment: VIRTUAL_HOST: "*.web.local,*.back.local" networks: - default - front back: build: context: ./back depends_on: - web networks: front: external: true
環境依存
$ cat env1.yml version: "3.5" services: web: environment: VIRTUAL_HOST: "env1.web.local,env1.back.local" APP_ENV: env1 volumes: - ./web/env1.html:/usr/share/nginx/html/index.html:ro back: volumes: - ./back/env1.html:/usr/share/nginx/html/index.html:ro networks: default: name: env1 $ diff env1.yml env2.yml 5c5 < VIRTUAL_HOST: "env1.web.local,env1.back.local" --- > VIRTUAL_HOST: "env2.web.local,env2.back.local" 7c7 < - ./web/env1.html:/usr/share/nginx/html/index.html:ro --- > - ./web/env2.html:/usr/share/nginx/html/index.html:ro 10c10 < - ./back/env1.html:/usr/share/nginx/html/index.html:ro --- > - ./back/env2.html:/usr/share/nginx/html/index.html:ro 14c14 < name: env1 --- > name: env2
- 前のファイルで定義した同じフィールドの項目が後のファイルにあれば、それを上書きします。
- 新しい値があれば追加します。
例えば、
environment
の同じキー (VIRTUAL_HOST
) は上書きされますenvironment
の異なるキー (APP_ENV
) は追加されますvolumes
は追加されます
最終的にどんな設定になるのかは、 docker-compose config
コマンドを使うと見れます。
$ docker-compose -f docker-compose.yml -f env1.yml -p env1 config networks: default: name: env1 front: external: true name: front services: back: build: context: /home/ikasamak/work/dc-multi-env/back depends_on: - web volumes: - /home/ikasamak/work/dc-multi-env/back/env1.html:/usr/share/nginx/html/index.html:ro web: build: context: /home/ikasamak/work/dc-multi-env/web environment: APP_ENV: env1 VIRTUAL_HOST: env1.web.local,env1.back.local networks: default: null front: null volumes: - /home/ikasamak/work/dc-multi-env/web/proxy-to-back.conf:/etc/nginx/conf.d/proxy-to-backi.conf:ro - /home/ikasamak/work/dc-multi-env/web/env1.html:/usr/share/nginx/html/index.html:ro version: '3.5'
-p, --project-name オプション
プロジェクト名を指定します。 デフォルトは compose ファイルのあるディレクトリ名です。
~/work/dc-multi-env master* $ docker-compose up -d Creating network "dc-multi-env_default" with the default driver
プロジェクト名を指定せずに同じディレクトリで別環境を立ち上げると、 同プロジェクトの同サービスと見なされ、既存のコンテナがかき消されてしまいます。
$ docker-compose -f docker-compose.yml -f env1.yml up -d Creating network "env1" with the default driver Creating dc-multi-env_web_1 ... done Creating dc-multi-env_back_1 ... done $ docker-compose -f docker-compose.yml -f env2.yml up -d Creating network "env2" with the default driver Recreating dc-multi-env_web_1 ... done Recreating dc-multi-env_back_1 ... done $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ffd5b9f636be dc-multi-env_back "nginx -g 'daemon of…" 5 minutes ago Up 5 minutes 80/tcp dc-multi-env_back_1 6dcafba12120 dc-multi-env_web "nginx -g 'daemon of…" 5 minutes ago Up 43 seconds 80/tcp dc-multi-env_web_1
-p
でプロジェクト名を指定し、別環境として立ち上げます。
$ docker-compose -f docker-compose.yml -f env1.yml -p env1 up -d Creating network "env1" with the default driver Creating env1_back_1 ... done Creating env1_web_1 ... done $ docker-compose -f docker-compose.yml -f env2.yml -p env2 up -d Creating network "env2" with the default driver Creating env2_back_1 ... done Creating env2_web_1 ... done $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2496c6858e0c env2_web "nginx -g 'daemon of…" 4 seconds ago Up 3 seconds 80/tcp env2_web_1 fa5bcec301ad env2_back "nginx -g 'daemon of…" 5 seconds ago Up 4 seconds 80/tcp env2_back_1 0aca011671e7 env1_web "nginx -g 'daemon of…" 12 seconds ago Up 11 seconds 80/tcp env1_web_1 ec885d01fa73 env1_back "nginx -g 'daemon of…" 13 seconds ago Up 12 seconds 80/tcp env1_back_1
プロジェクト名を指定する方法
-p, --project-name
オプションを使うCOMPOSE_PROJECT_NAME
を使う- 環境変数を
.env
ファイルで指定する
- 環境変数を
Compose ファイルにプロジェクト名を指定できれば楽なんですけど、そういう仕様にはならなかったようです。
まあ普通は環境ごとにディレクトリ分けるから、 .env
で何とかしなさいということなんでしょう。
networks
適切にネットワークを設定しないと、コンテナ名で名前解決していると別環境にトラフィックが飛んでしまうことがあります。
例えば、面倒なんで全部 front のプロキシのいるネットワークにつないでしまえ! ということをすると
$ cat docker-compose.yml version: "3.5" services: web: build: context: ./web volumes: - ./web/proxy-to-back.conf:/etc/nginx/conf.d/proxy-to-back.conf:ro environment: VIRTUAL_HOST: "*.web.local,*.back.local" networks: - front depends_on: - back back: build: context: ./back networks: - front networks: front: external: true
env1
の web
が env1
, env2
両方の back
とつながるので、
back
へのアクセスがロードバランシングされてしまいます。
$ curl -H "Host: env1.back.local" localhost here is env2.back! $ curl -H "Host: env1.back.local" localhost here is env1.back! $ curl -H "Host: env1.back.local" localhost here is env2.back! $ curl -H "Host: env1.back.local" localhost here is env1.back!
なので、適切にネットワークを設定しましょう。
プロジェクト名を分けているのであれば、 default
で通信するようにしましょう。
*2
おまけ
extends
を使えば、設定をモジュール化して再利用できるようです。
2019/03/08 追記
extends
は compose file format v3 で使えなくなってました。
まとめ
- 共通部分、環境依存部分に分けることで Compose ファイルを DRY に書けます
-p
オプションでプロジェクト名を分け、同じサービス名を別環境で同時に動かせるようにしますnetworks
を適切に設定して別環境にトラフィックが迷い込まないようにします
参考
- Overview of docker-compose CLI | Docker Documentation
- Compose file version 3 reference | Docker Documentation
- Networking in Compose | Docker Documentation
*1:https://twitter.com/ito_yusaku/status/1042604780718157824
*2:サービス名だけの名前解決 ( http://back とか ) は、default ネットワークから行われるようです
YAML で履歴書を作るを Docker 環境でやってみた
- 最近、転職を考えるようになっていろいろ行動し始めた
- 履歴書や職務経歴書を要求される場面が増えてきた
- 以前転職したときはインターネットのどこかでダウンロードした Microsoft Word のテンプレートで作成したものを PDF に変換して使ってた
- 必要な情報をアップデートしたらそれだけで履歴書を更新できるような仕組みにしたい
- いい感じのがある
というわけで、さっそくやっていきましょう。
実行環境
必要なライブラリ等 にあるように、 Prawn と IPAex フォントがあれば動きます。 あと Ruby の Script なので当然 Ruby も。
これくらい軽量ならサクッとローカル環境にインストールしてしまってもいい気がするんですが、せっかくなので実行環境を Docker 化してみました。
2023/09/24 追記
本家の変更に追従しやすくするよう、本家を Fork したリポジトリに追加する形に変更し、docker-yaml_cv はアーカイブしました。 以降はこちらを利用ください。
$ docker compose up [+] Running 1/0 ✔ Container yaml_cv-app-1 Created 0.0s Attaching to yaml_cv-app-1 yaml_cv-app-1 | ruby make_cv.rb -i data.yaml -s style.txt -o output.pdf yaml_cv-app-1 | Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_checker)' instead. yaml_cv-app-1 | input file: data.yaml yaml_cv-app-1 | style file: style.txt yaml_cv-app-1 | output file: output.pdf yaml_cv-app-1 | Done. yaml_cv-app-1 exited with code 0
これだけで動く! 簡単!
git clone
したディレクトリ内でさらに kaityo256/yaml_cv を git clone
し、 docker-compose up
します。
$ docker-compose up Creating network "dockeryamlcv_default" with the default driver Building make_cv Step 1/5 : FROM ruby:alpine ---> 8ea9c590ec75 ... 省略 ... make_cv_1 | input file: data.yaml make_cv_1 | style file: style.txt make_cv_1 | output file: /output/output.pdf make_cv_1 | Done. dockeryamlcv_make_cv_1 exited with code 0 $ ls -l output.pdf -rw-r--r--. 1 root root 109173 Jan 28 05:51 output.pdf
しかし、 JIS 規格の履歴書とやらは冗長だ
資格や通勤時間といった情報はともかく、趣味・特技や志望動機なんて履歴書に必要なのか?
ということで、 fork して A4 1 ページに収まるスタイルも作ってしまいました。
課題
スクリプトを Dokcer で動かすため、出力される PDF のファイルオーナーが root になってしまいます。 これは fixuid というものを使えば解決できそうです。
まとめ
- YAML で履歴書を作るスクリプト kaityo256/yaml_cv の実行環境を Docker で作りました
- A4 1 ページに収まるスタイルを作りました
謝辞
@kaityo256 さんありがとう!
参考
Amazon Echo Dot から Fire TV Stick を操作する
様子
Echo Dot と Fire TV Stick のある生活 pic.twitter.com/t9SNGTG9sp
— ɐɯɐsɐʞ! (@ikasamak) 2018年12月15日
設定方法
1. Amazon Alexa アプリのサイドメニューを開いて 設定
をタップ
2. ALEXA の環境設定
-> TV・ビデオ
をタップ
3. firetv
をタップ
4. Alexa デバイスをリンク
をタップ
5. Fire TV Stick を選択して 続行
をタップ
6. Echo Dot を選択して デバイスを接続
をタップ
7. 接続完了!
Echo Dot 第3世代 (Newモデル) - スマートスピーカー with Alexa、チャコール
- 出版社/メーカー: Amazon
- 発売日: 2018/10/30
- メディア: エレクトロニクス
- この商品を含むブログを見る
- 出版社/メーカー: Amazon
- 発売日: 2017/04/06
- メディア: エレクトロニクス
- この商品を含むブログ (17件) を見る
Heroes of Hammerwatch Patch notes for version 87 を訳した
Heroes of Hammerwatch とは?
一言でいうと
公式ページ
Steam
ちょうど新パッチのトレイラーがあった
Patch notes のソース
おことわりと謝辞
- 一部翻訳間違いなどがあるかもしれません。気が付いたら指摘ください。
- ゲーム内の固有名詞の翻訳にあたっては、以下の日本語化 MOD を参考にしています。ゲームでも使ってます。感謝!
Steam Workshop :: Japanese Translation
以下、翻訳内容
- 新しいステージ 6
Battlements
( 2 フロア ) 追加 - ステージ 5
議会
のマップを大きくしたが、フロアを 2 フロアに削減 - ショートカット・ポータルのステージを改変
- Mod サポートを追加
クラス
シーフ
- レベルアップによる HP 上昇量を 4 から 5 に増加
回避
はこれまでの効果に加え、時間経過によって追加で 1 回の回避判定をスタックする- 要するにスタックした状態だと最大 2 回の回避判定になる
鉤なわ
の当たり判定を大きくした
ソーサラー
ウィンターオーブ
で射出されるかけらは敵に当たると反射/貫通するフロストシャード
は敵に貫通/反射するたびにダメージが 10% 増加する痛烈な冷気
の凍結確率が 5% から 7.5% に増加
ウォーロック
- 基礎 HP が 75 から 60 に減少
ソウルダガー
がヒットごとにダメージを与えるようになるが、ヒットによるダメージ量は -2 される
ウィザード
ブラストウェーブ
のレベル 3,4 において正しい焦土
を設置するようになる
プリースト
聖なる光
に小さな AOE を追加
レンジャー
獲物の印
のデバフを付与したときに同時にクリティカルが発生するパワーショット
のチャージ中にゆっくり動けるようになる *1矢の突風
のクールダウンが 2 秒から 0.75 秒に短縮
アイテム/酒
- アイテム/酒をいろいろ追加
- 酒のストックがあると無料で飲めるようになる
- ストックがないときはより高い金額を払えば飲めるようになる
スピードブーツ
が 2 つのセットアイテムに分割される- それぞれが以前の
スピードブーツ
と同じくらいの効果を与える
- それぞれが以前の
- 以下のアイテムのクールタイムが減少する
アーススプリッター
ストームコーラー
雷神の怒り
守護のスカラベ
降りかかる破壊
スパイクブーツ
のダメージ量が 15 から 25 に増加ストームコーラー
のチェインライトニングの射程が増加降りかかる破壊
のダメージ量と燃焼時間が増加補強グローブ
のダメージブロック量が増加
変更と修正
- ステージ 3
武器庫
の儀式の像
のボタンを押す必要がなくなった - クラスタイトルが無限に増加するようになる
- アイテム同調のポイント再分配とスキルのポイント再分配がそれぞれ別に行えるようになる
- 最後のボスを倒した際の税率が減少
- 各ステージのフロア 1 ではショップが出現しなくなる
- ショップに新しいバリエーションを追加
- マナ減少のデバフが絶対量ではなく、最大マナ量の割合で減少するようになる
- インプ出現のアナウンスを追加
- モノリスのバフとして
ゴールドフィーバー
を追加 - ゲームオーバーの画面にとどめを刺した敵のアイコンを表示
- 2,3 人でマルチプレイしているときの敵の HP 倍率が減少
- ロックされている教会のアップグレードのコストを表示
- 染料の追加
- 統計の数値が 20 億を超えてもバグが起きないようになった
- キャラクターメニューで表示される攻撃やスキルのアイコンをツールチップの中に移動
- フレーム制限の精度向上
- 壁の中に埋まる現象についての実験的な修正
- 街でリロードすると
エースキー
が複数付与されるのを修正 - ときどき発生する画面クラッシュ *2 の修正
- 新しい効果音の追加
Apache HTTP Server の ServerLimit を変更するための再起動方法
結論
apachectl
apachectl stop; apachectl start;
SysVinit 系
service httpd|apache2 restart
systemd 系
systemctl restart httpd|apache2
解説
Apache HTTP Server のドキュメントによると ServerLimit
は apachectl restart
で無視されるとあります。
mpm_common - Apache HTTP サーバ バージョン 2.4
実際、 ServerLimit
を変更して apachectl restart
すると以下のようなログが出ます。 *1
これは ServerLimit
を 16
から 32
に変更した場合です。
[Mon Sep 24 13:36:35.613950 2018] [mpm_prefork:warn] [pid 1788] AH00179: changing ServerLimit to 32 from original valueof 16 not allowed during restart
というわけで、 ServerLimit
を変更したときは apachectl stop; apachectl start;
に相当するコマンドで再起動をしましょう。
service
や systemctl
による Apache HTTP Server の起動停止がどういう挙動をしているかは、以下を参考にそれぞれの起動停止スクリプトを読んで理解しましょう。
AWS EC2 に OpenVPN を構築して Chromebook から接続するときにハマったポイント
OpenVPN 2.4によるVPN接続環境をAWSで構築する | DevelopersIO
Chromebook から OpenVPN(TLS-Auth、LZO圧縮有り)へ接続してみた - Qiita
基本はこの2つのあわせ技です。 作業内容のほとんどはそれぞれの記事を参考にしてもらえば。
個人的にハマったところ
インターネット向けのトラフィックを全部 OpenVPN 経由にするとき
OpenVPN の server.conf
に以下のような設定を書きます。
push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 192.168.1.1"
このとき、dhcp-option DNS
で指定する DNS サーバのアドレスは、 OpenVPN サーバから到達できるものを指定してください。
何故なら、名前解決も全部 OpenVPN サーバから実行するからです。
最初これがわかってなくて、無限に名前解決に失敗してインターネットに出られなくなった。
AWS EC2 上で構築するなら、AmazonProvidedDNS を指定するのが良いかもしれません。
たとえば VPC のネットワークが 172.30.0.0/16
だったら、AmazonProvidedDNS は 172.30.0.2
になります。
固定で 169.254.169.253
も使えるみたいですけど、試してません。
詳しくはこちら↓。
Chromebook から接続するときはパスワード欄の入力が必須
クライアント証明書をパスワード設定せずに作成した場合でもパスワード欄に何かしらの文字列の入力が必要です。 空欄だと接続しに行ってくれません。
サーバー側の設定と ONC ファイルの設定を合わせる
ONC ファイル作るのが面倒だったんでベースの作成にこれを使いました。
ただ、2018/05/28 時点でそのまま使うのはちょっと微妙で、いくつか手を入れないといけなかったです。
"Proto": udp
と出力されるので"Proto": "udp"
に直す必要がある。udp
にダブルクォーテーションがなくて JSON Syntax Error になる
- クライアント証明書が埋め込まれてしまっているので、デバイスにインポートしたものを使う場合は要修正
"Auth": "SHA512"
がサーバ側のデフォルト設定と異なる- サーバ側に
auth SHA512
を設定するか、ONC ファイルから"Auth": "SHA512"
を消す
- サーバ側に
Source IP アドレスを OpenVPN サーバのものにしたい
IP Masquerade しましょう。
$ sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
以上、楽しい VPN ライフを!
他の参考サイト
Chromebook で iso イメージを USB フラッシュメモリに焼く
背景
- メインマシン (Windows10) がクラッシュを繰り返してとうとうレジストリ破損で起動しなくなった
- OS クリーンインストールをしようと思ったけどインストールメディアがない
- サブマシンである Chromebook でインストールメディアを作成しよう! ← いまここ
確認した動作環境
- ASUS Chromebook Flip C100PA
- Chrome OS バージョン: 67.0.3381.0(Official Build)dev (32 ビット)
ASUS Chromebook Flip ノートパソコン C100PA/Chrome OS/10.1型/Quad-Core RK3288C/2G/eMMC 16GB/タッチ/C100PA-RK3288
- 出版社/メーカー: Asustek
- 発売日: 2015/10/03
- メディア: Personal Computers
- この商品を含むブログを見る
手順
1. Ctrl + Alt + T で ターミナルを開く
2. shell
でシェルを起動
crosh> shell chronos@localhost / $
3. df
で USB フラッシュメモリっぽいのを見つける
chronos@localhost / $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 1640868 1446944 193924 89% / devtmpfs 1031524 0 1031524 0% /dev tmp 1031736 176 1031560 1% /tmp run 1031736 476 1031260 1% /run shmfs 1031736 25656 1006080 3% /dev/shm /dev/mmcblk0p1 10801712 9147840 1085452 90% /mnt/stateful_partition /dev/mmcblk0p8 11760 24 11412 1% /usr/share/oem /dev/mapper/encstateful 3185468 135304 3033780 5% /mnt/stateful_partition/encrypted media 1031736 0 1031736 0% /media none 1031736 0 1031736 0% /sys/fs/cgroup imageloader 1031736 0 1031736 0% /run/imageloader /dev/dm-2 12476 12476 0 100% /run/imageloader/PepperFlashPlayer tmpfs 1031736 4 1031732 1% /run/arc/oem tmpfs 1031736 0 1031736 0% /run/arc/sdcard tmpfs 1031736 0 1031736 0% /run/arc/obb tmpfs 1031736 0 1031736 0% /run/arc/media tmpfs 1031736 0 1031736 0% /run/arc/adbd /dev/fuse 10801712 9147840 1085452 90% /run/arc/sdcard/default/emulated /dev/fuse 10801712 9147840 1085452 90% /run/arc/sdcard/read/emulated /dev/fuse 10801712 9147840 1085452 90% /run/arc/sdcard/write/emulated passthrough 1031736 0 1031736 0% /run/arc/media/removable /dev/sda 3704296 3704296 0 100% /media/removable/RHEL-7.3 Server.x86_64
今回は /dev/sda
がそれっぽい。前に RHEL7
の起動ディスクにしたやつだった。
4. dd
で iso ファイルを焼く
$ sudo dd if=./Win10_1709_Japanese_x64.iso of=/dev/sda