今更まとめるdockerコンテナの開発Tips

March 8, 2017

最近ようやっと本格的に触りだしたので備忘録的に書きます。

プラクティスやアンチパターン的な話なので、 いわゆるチートシートやチュートリアルについては他記事を参照ください。

Dockerfile関連

FROMは慎重に選ぶ

  1. なるべく公式のDockerfileを使う。
  2. ユーザーコンテナは自分でDockerfileを作成する時の参考に
    • Download数の多いDockerfileは特に参考になる
  3. 軽量コンテナについて
    • はじめはなるべく標準のコンテナを使い、軽量コンテナの使用は一旦避ける
    • まずはコンテナ運用のメリット・デメリットを体感し自分が求めるものかどうかを見極める
    • 軽量コンテナ自体はnode:7-slim,golang:alpineなど公式的に提供されているので使う場合はこれらを使う
    • 軽量コンテナの検討や導入は、既にDockerを運用していたり大量配備にまつわる悩みを抱える段になってからでも遅くはない
    • 依存関係のトラブルはハマると時間食い虫なので注意
    • 例えば3rd Partyのライブラリを使用したいときなど

Dockerfileのお作法

  1. とりあえず公式のBestPracticesを一読。
  2. ENTRYPOINTをベースコマンドとして使い、デフォルト引数としてCMDを使う
    • 適当にググるだけだとCMD使う例が多くヒットするので混乱する
    • 要するにsh -cENTRYPOINTの初期値で、その引数がCMDという位置づけ、ENTRYPOINTナシでCMDだけ書いても動くのはこれが理由
  3. ADDはリモートからのリソース取得ができる、curl,wgetの代わりだと思えばよい
    • ADDには他にもtarによるローカル圧縮ファイルの自動解凍の仕組みが備わってる
    • 便利っちゃ便利だが、わからず使ってると混乱するかも
  4. COPYは単純なローカルからコンテナへのファイル転送として使う
    • ADDと住み分ける
  5. RUN cd && commandではなくWORKDIRを使う
  6. ホストボリュームのマウントをコマンドラインから指定するかDockerfile内のVOLUMEで指定するかはケースバイケース
    • まだあまり使い込んでいないので、もうちょっと使い慣れたらUpdateしたい
    • ストレージドライバまわりの話から察するに結局NFS運用がつらい的な問題にぶつかりそうな気配

ディレクトリ構成

レイヤーを考慮した結果、だいたい以下のような構成になった。

.
├── base
│   └── Dockerfile
├── middleware
│   ├── Dockerfile
│   └── middleware.conf
├── app
│   └── Dockerfile
└── README.md
  • 各Dockerfileごとに必要な設定ファイルは当該ディレクトリ内に同居させる
    • Nginxのconfやfluentdのconfなど
    • MySQLコンテナ内の/docker-entrypoint-initdb.dに設置したいfixture.sqlなど

レイヤーを効果的に使う

  1. レイヤーを細かく切るほうがビルド待ち時間を減らせる
    • 既にAnsibleやChefの資産があるのならroleの概念をそのままレイヤーに置き換えて考えれば悩みが減る
    • 変更余地の無さそうなコマンドは早めにbaseレイヤーやpackages,middlewareレイヤーなどの名前をつけて切り分ける
    • レイヤーを活用することでビルドの待ち時間を削減でき、効率的な編集作業が可能になり、原因の切り分けもしやすくなる。
  2. USERをDockerfile内で何度も切り替えるのはどちらかというと悪手
    • でもsudoを使うよりはマシ
    • はじめにrootで依存をまとめて入れておき、以後のレイヤーでUSERを切り替えてRUN,EXPOSE,ENTRYPOINTとするのが良さそう。
    • しかし、defaultでrootを強制するのはやっぱりやめてほしい…
  3. 作業中はホストマシンのディスクの空き容量に注意
    • レイヤーが多いと必然的にイメージも増える。
    • Docker開発マシンには256GB,512GBなどのサイズの大きいSSDが望ましい。

よく使うワンライナー

ビルドと動作確認

  1. docker build -t username/appname -f role/Dockerfile role/
    • ディレクトリ構成の項で言及した通りroleの箇所はbase,packages,rubyなど、AnsibleやChefのRoleにならったディレクトリパスに。
    • username/appnameの部分は別に自由でいいが一旦dockerhubのセオリーに則っておく。チーム開発ならusernameのところをorganizationやチーム名などにしてもよい。
    • 末尾のrole/は当該Dockerfileのあるディレクトリを指定。.だとカレントディレクトリ以下の全ファイルを対象にビルド前チェックが走るので、レイヤーごとに個別にディレクトリ指定をしておくのが無難。
  2. docker run --rm -it username/appname /bin/bash
    • あるいは、開発中はあらかじめDockerfile最下行にENTRYPOINT bashを書いておく。
    • bashが辛ければzshなどに変えてもいいが、buildし直すと意外と時間がかかって面倒くさい。
    • alias l='ls -lha --color'などをENTRYPOINTかその手前に入れておくだけでだいぶラクになる。
    • --rmを付けておくとコンテナ終了と同時にコンテナを消してくれる、経済的。
  3. docker logs $(docker ps -q)
    • コンテナIDを取りたいときは$(docker ps -q)などサブシェルを使うとわりとラクできる
    • grepしつつ複数rmやkillをしたいときは後述のようにsedawkで。

お掃除系

  1. docker rm $(docker ps -f status=exited -q)
    • Exitedなコンテナを指定して残りをrm
  2. docker rmi -f $(docker images -q -f "dangling=true")
    • ビルドやタグ付けに失敗したゴミイメージを消す。
  3. docker rmi -f $(docker images | sed 1,1d | egrep -v "app1|app2" | awk '{print $3}')
    • 残したいイメージをegrepで除外して残りをrmi
    • 依存関係にあるイメージは-fを指定してもエラーを出して削除対象から除外してくれる、安心設計。

DockerHub関連

準備

  • DockerHubのアカウントは作っておく
  • privateリポジトリは無料版ではひとつのみ、基本はpublicだと認識しておく
    • DockerHubに限った話ではないがpasswordcredentials等の取扱いには注意

セオリーを理解する

※MAINTAINERは最近deplicatedになったそうなので訂正しました

References



Recent blog posts



(c) Copyright 2026 Kotaro Yoshimatsu