Zademy

Docker と Docker Compose 完全ガイド:コマンドとベストプラクティス

Docker; DevOps; コンテナ; ガイド; CLI
words 単語

Docker と Docker Compose 完全ガイド:コマンドとベストプラクティス

Docker の基本概念

Dockerは、アプリとその依存関係をコンテナにパッケージ化するツールです。「私の環境では動くけど」という問題を、丸ごと1つの移植可能なユニットに押し込むことで解決します。

3つの概念を押さえれば、あとのコマンドは全部その周辺の話です。イメージはコンテナのテンプレートで、コード、ランタイム、ライブラリ、設定が全部入っています。コンテナはイメージを実際に動かしたインスタンスです。Docker Hubは、イメージを検索・共有するための公式サービスです。

Docker CLI コマンド(基本)

よく使うコマンドをまとめました。docker stopがSIGTERMを送って安全にシャットダウンしてくれる、という点だけ覚えておけば十分です。

タスクCLI コマンド説明
イメージ
イメージ構築docker build -t <image_name> .現在ディレクトリの Dockerfile からイメージを構築。
キャッシュ無し構築docker build -t <image_name> . --no-cacheキャッシュを使用せず強制的に再構築。
イメージ一覧docker imagesすべてのローカルイメージを表示。
イメージ削除docker rmi <image_name>ローカルイメージを削除。
未使用イメージ削除docker image prune未使用のすべてのイメージを削除。
Docker Hub へ公開docker push <user>/<image_name>イメージを Docker Hub へアップロード。
コンテナ
コンテナ実行(名前付き)docker run --name <container_name> <image_name>イメージからコンテナを作成・実行。
バックグラウンド実行docker run -d <image_name>分離モード(バックグラウンド)でコンテナ実行。
ポート公開付き実行docker run -p <host_port>:<container_port> <image_name>コンテナポートをホストへマッピング。
コンテナ一覧(実行中)docker ps現在実行中のコンテナを表示。
すべてのコンテナ一覧docker ps --all状態に関わらずすべてのコンテナを表示。
開始/停止/再起動docker start|stop|restart <container_name>既存コンテナの開始または停止。docker stop は SIGTERM シグナルを送り優雅にシャットダウン。
コンテナ削除docker rm <container_name>停止したコンテナを削除。
コンテナ内に入るdocker exec -it <container_name> sh実行中のコンテナ内にインタラクティブシェルを開く。
ログ表示docker logs -f <container_name>コンテナログを表示・追跡。
コンテナ検査docker inspect <container_name>コンテナ詳細を表示(通常 JSON 形式)。
リソース監視docker statsランタイムリソース使用統計を表示。

高度な Docker:イメージとセキュリティのベストプラクティス

マルチステージビルド

マルチステージビルドを使うと、開発に必要なツールを本番イメージに含めずに済みます。出来上がるイメージが小さく、攻撃面も減る。実務では必須のテクニックだと思います。

やり方は複数のFROM命令を使うだけです。各FROMが新しいステージを開始します。COPY --from=<stage>で前のステージから成果物だけをコピーして、FROM <image> AS <NAME>でステージに名前を付けておくと参照しやすいです。たとえばCOPY --from=build /bin/hello /bin/hello。

デバッグが必要なときはdocker build --target <stage> -t hello .で特定ステージまでのビルドに留められます。BuildKitが有効なら、ターゲットに必要なステージだけ処理されるので速いです。

イメージとコンテナのセキュリティ

セキュリティは「攻撃面を減らす」積み重ねです。ここに挙げる項目は、どれか一つが銀弾というわけではありませんが、全部やればかなり堅くなります。

まずベースイメージ。公式の検証済みイメージを使い、最小ベースから始めて必要な依存だけ追加する。脆弱性はTrivyやDocker Scoutで定期的にスキャンします。

実行ユーザーはroot以外で。コンテナは可能な限り読み取り専用ファイルシステムで動かす。イメージの改ざん防止にはDocker Content Trust (DCT)を有効にして、署名済みイメージだけを使うようにします。

Docker Compose(マルチコンテナアプリケーション管理)

Docker Composeは、docker-compose.yml1つで複数コンテナを定義・起動できるツールです。Webアプリ、データベース、キャッシュなど、協調動作するサービス群を一元管理できます。

Docker単体だとコンテナごとにコマンドを打つ必要がありますが、Composeなら定義ファイル1つで全体を上げ下げできます。開発・テスト環境で特に重宝します。

バージョンについて。V1(docker-compose、ハイフン付き)は更新が止まっています。V2はdocker compose(ハイフンなし)を使います。今から始めるならV2一択です。

Compose 構造と基本コマンド

docker-compose.ymlの基本構造はこうなります:

# 注:最新 Docker Compose バージョンではバージョン指定は不要
# version: '3.8'  # 現代バージョンではオプション
services:
  service1: # コンテナ/サービス定義
    # サービス設定
networks:
  network1: # カスタムネットワーク設定
    # ネットワーク設定
volumes:
  volume1: # 名前付きボリューム定義
    # ボリューム設定
タスクCLI コマンド(V2)説明
構築と展開docker compose upyml で定義されたコンテナを構築・実行。
バックグラウンド展開docker compose up -d展開しアプリをバックグラウンドで実行。
アプリ停止docker compose stopコンテナを停止。
停止と削除docker compose downサービスとネットワークを停止・削除。デフォルトで名前付きボリュームは削除しない。
ボリューム付き削除docker compose down --volumes または -vサービス、ネットワーク、名前付きボリュームを強制削除。
サービススケールdocker compose up --scale service=n特定サービスのコンテナ数(n)を増加。
サービスステータスdocker compose psコンテナの現在ステータスを表示。
ログdocker compose logs定義コンテナのログを表示。

永続データ管理(ボリューム)

コンテナは停止すると中身が消えます。データベースのデータやユーザーアップロードファイルを残すには、ボリュームが不可欠です。

名前付きボリュームは、ymlのvolumesセクションで定義してサービスにマウントします。管理しやすくて、明示的に消さない限り残ります。ホストマウント(バインドマウント)は、ホストのディレクトリを直接コンテナに共有する方式で、/path/on/host:/path/in/containerという構文です。開発中にソースコードの変更を即座にコンテナに反映したいときに便利です。

タスクCLI コマンド(Docker、Compose ボリュームに適用)
ボリューム一覧docker volume ls
ボリューム検査docker volume inspect <volume_name>
ボリューム削除docker volume rm <volume_name>
未使用ボリュームクリーンdocker volume prune

Compose の高度な本番ベストプラクティス

シークレットと環境変数管理

データベースのパスワードやAPIキーをコードに直書きしてはいけません。これは本当にやらかしやすいポイントです。イメージレイヤーに残って、後からdocker historyで丸見えになります。

.envファイルに環境変数を保存し、docker-compose.ymlでenv_file: .envとして参照するのが基本パターンです。ただし、この.envファイルは必ず.gitignoreに入れてください。Gitに突っ込んだ瞬間に意味がなくなります。

ネットワークとアクセスセキュリティ

Composeで定義したコンテナは、デフォルトで内部ネットワーク上で相互に通信できます。これを利用して、データベースのポートをホストに公開しない、という設定をするとよいです。ymlからポート公開を削除するだけで、データベースには同じComposeネットワーク内からしかアクセスできなくなり、外部から隠せます。ホストからアクセスしたい場合はSSHトンネルを使います。

リソース制限と再起動

共有サーバでコンテナを動かすなら、リソース制限は必須です。一つのサービスがCPUやメモリを食いつぶして、他のサービスに影響が出るのを防げます。

deploy: resourcesでメモリ、CPU、GPUの制限を指定します。limitsはそのコンテナが使える上限、reservationsは予約量です。restart: alwaysを付けておけば、サーバ再起動時にも自動でコンテナが立ち上がります。on-failure、遅延(delay)、最大試行回数(max_attempts)などで細かく条件を絞ることもできます。

ヘルスチェック

コンテナが「実際に動いているか」を定期的に確認する仕組みです。単にプロセスが生きているだけでなく、HTTPリクエストに応答するかとか、DB接続できるかをテストして、失敗したら再起動します。

設定項目はinterval(テストの頻度)、retries(ダウンとみなす失敗回数)、timeout(タイムアウト時間)、start_period(起動時の猶予)です。

ホストセキュリティと一般的ベストプラクティス

Docker Engineが動くLinuxサーバ自体のセキュリティも大事です。コンテナがどれだけ堅くても、ホストが落ちたら終わりです。

Rootでのログインは無効にする(Ubuntu Serverならデフォルトで無効)。SSHログインはパスワードではなくRSAキーを使う。ssh-keygenで鍵を作って、ssh-copy-id <user>@<server>で公開鍵をサーバに登録します。

ブルートフォース対策にFail2Banを入れます(apt install fail2ban)。SSHへの失敗が多いIPを自動でブロックしてくれます。あとはDocker Engineと依存関係のこまめな更新、docker statsでのリソース監視、ログの記録と監視システムの導入。地味ですが、これらが効いてきます。


このガイドのコマンドとプラクティスを一通り試せば、開発から本番までDockerで困ることはほぼなくなります。次に掘るとしたら、Kubernetesでのオーケストレーションか、イメージサイズと起動時間をさらに削る最適化手法あたりでしょうか。