入門docker 復習(6)

プロダクションでの活用

イメージの仕組み

Container

  • DockerImageはReadOny
  • Docker Containerを作成することで変更可能なレイヤーが生成され、レイヤーの上でプロセスを動かす
  • docker diffによりコンテナ起動後に変更されたファイルを確認できる

Unison FileSystem

  • Containerレイヤーに操作対象のパスが存在しない場合、Imageレイヤーにファイルが無いか確認する
  • Docker ContainerからDocker Imageへファイルを読み込む際は1レイヤーごとに操作するため、オーベーヘッドが大きくなる可能性がある
  • dockerのデフォルトのファイルの読み書きはコピーライトオン形式(元データは変更せず、新規更新を新たな場所に書き込みむこと)のため、ファイルの更新頻度が高いログなどはDataVolumeを使用してオーバーヘッドを小さくするべき

Dockerイメージ

  • イメージは複数のイメージの積み重ねで出来ている
  • 積み重なったイメージを中間イメージと呼ぶ、docker history <イメージ名>で確認可能
  • RUNコマンドをパイプで繋げることで中間イメージを減らし、軽量化が可能になる
  • レイヤーを作成するコマンド(RUN , COPY , ADD )を極力増やさない

Dockerfileのベストプラクティス

軽量なイメージを作る

  • イメージはサイズが軽く、レイヤーが少ないものが良い
  • サイズが思いpullに時間がかかり、レイヤーが増えるとオーバヘッドが増加する

最小限の構成にする

  • 1コンテナ1プロセスにする
  • 複数のプロセスを使用する場合は、それぞれのコンテナに分けてオーケストレーションツールによりコンテナを協調させる

軽量なベースイメージを使用する

  • Alpine OSという軽量なOSでイメージを作成する

.dockerignoreを使う

  • Dockerfileのビルド時に無視するファイルやディレクトリを指定する
  • .gitのようなコンテナ内に不要な情報、node_modulesのような上書きされると困るものを記載する

Build

キャッシュを意識する

  • DockerImageは各コマンド毎にキャッシュを作成する(中間レイヤー)
  • ビルド後にファイルに変更があった場合、変更直前のキャッシュからビルドを実行する

Multi-Stage Build

  • 複数のDockerImageを作成し、その中から特定のファイルを抽出して1つのDockerImageを作成する

入門docker 復習(5)

プロダクションでの活用

設計

1コンテナ=1プロセス

  • Dockerは1プロセスをフォアグラウンドで走らせるため、1コンテナ=1プロセスの粒度で設計する
  • ただし、設計上1プロセスが難しい場合は1コンテナにつき1つの関心事にする

永続的なデータはマネージドサービスに任せる

  • 永続的なステータスにより依存が発生した場合、Dockerの性能に影響を及ぼす
  • ステートを持たない設計をする

セキュリティ

rootユーザーを使わない

  • コンテナ内に侵入された時の影響を最小限にするため
  • Docer Imageのデフォルトがrootユーザーのため注意が必要
  • USERコマンドでユーザーを変更する

野良のDocker Imageをベースイメージにしない

  • ユーザー製のイメージは過去に何度もマイニング(処理能力が使われる)や攻撃を受けているため
  • ベースイメージは公式のものを使用する

ビルド時に機微情報を与えない

  • ビルド時に秘密鍵やパスワードなどを与えない
  • どうしても必要な場合は--secret--sshオプションを使用してセキュアにビルドする
  • パスワードや接続情報は環境変数やVault(セキュリティフォルダ)へ格納する

ホストのファイルのマウントの仕方

  • ホストのファイルをマウントする際は最小限の権限とパスで範囲を狭くする
  • 特にdockerソケットはCIや監視でマウントを要求するソフトが増えてきている
  • ソケットをマウントする場合はRead-Onlyでマウントする

.dockerignoreファイルを使う

  • Dockerビルド時に無視するパスを記述するファイル
  • .envなどのDBへの接続情報や.gitnode_modulesのようなビルドに不要なパスは無視することでビルドが高速かつイメージが軽量になる

デバッグ

  • イメージの確認
    • docker images
  • ホスト上の全てのコンテナを確認

    • docker container ls -a
    • 実行中のコンテナだけ確認 docker container
  • コンテナの停止

    • docker stop <コンテナID>
    • 全コンテナの停止 docker stop $(docker ps -q)
  • コンテナの削除

    • docker rm <コンテナID>
    • 全コンテナの削除docker rm $(docker ps -q -a)
  • イメージの削除

    • docker rmi <イメージID>
    • 全イメージの削除docker rmi $(docker images -q)
  • コンテナにログインしてbashで操作(起動中のみ)

    • docker exec -it <コンテナID> bash
  • コンテナのログを確認

    • docker logs <コンテナID>
    • 起動したプロセスの標準出力と標準エラーのログのため、ファイルに書き込まれるログは確認出来ない
  • 停止したコンテナに入る

    • 停止したコンテナから新しいイメージを作成する
      • docker commit <コンテナID> <新しいコンテナ名>
    • 新しいコンテナにログインする
      • docker run -it exited-container bash

入門docker 復習(4)

コンポーネント

network

Networkを使用する

  • nginxとphp-formのような複数プロセスを動かす必要がある場合、ソケットではなくネットワークで通信を行うことが推奨されている
  • Kubernetes,ECS,docker-composeのような各種オーケストレーションツールを使用する際に意識する必要がある

Driverの種類

  • ネットワークの振る舞いを2種類から定義することが可能
    • brige
      • Linuxカーネルのbridgeネットワークを使用する機能
      • 指定なしでContainerを起動するとdocker0のネットワークに所属する
    • host
      • ホストマシンのeth0を使用する
    • none
      • 起動したコンテナをネットワークに所属させない設定
  • 1プロセスは1コンテナ、複数コンテナはネットワークを通して通信を行う

volume

volumeについて

  • データを永続化するための機能
  • コンテナ上で作成されたファイルはライフサイクルの終了と共に消える
  • Volumeはデータ保存、永続化のために設計されており、コンテナのライフサイクルとは独立してファイルの管理を行う

volumeType

  • Data Volume
    • ライフサイクルの外で管理されるファイル/ディレクトリの設定
    • -v <CONTAINER PATH>
  • Data Volume Container

    • 他のDockerContainerで指定されているVolumeを参照・共有するための機能
  • Dockerはエフェメラル(一時的)になるように設計されているため、Volumeは使用しないことが望ましい

入門docker 復習(3)

コンポーネント

container

Docker Containerとは

  • Docker Image がスナップショットだとしたらDocker Container「スナップショットから起動したプロセス」
  • docker run を実行するとDocker Image をもとにしてDocker Containerが作成され、隔離された環境が作成される
  • Docker Container は Docker Imageを元にして作成され、リソースの許す限り立ち上げることが可能
  • Docker Container は1つのコマンドをフォアグラウンドで動かすように設計されている
  • Docker Containerは1つのコマンドを隔離された環境で実行し、そのコマンドの実行がフォアグラウンドで終了するまで生存する

ライフサイクル

  • Docker Container は5つの状態を遷移する

  • Image

    • 指定したDocker Image からDocker Containerを起動する
  • RUNNING
    • Docker Containerが起動した状態
    • Dockerfileの CMD もしくは ENTRYPOINT で指定したコマンドがフォアグラウンドで動いている間がRUNNINGの状態
    • docker run -P nginx のようにnginxを起動した場合、nginxが起動してアクセスを待ち受けてる間はRUNNINGの状態
  • STOPPED
    • 起動したContainerが終了した状態
    • 正常終了・異常終了、どのような形であっても終了したContainerはSTOPPEDへ遷移
  • PAUSED
    • Containerが停止した状態
    • ユーザーが docker pause <CONTAINER ID> を実行すると、現在の状態を保持して一時停止
    • docker unpause で一時停止したコンテナIDを指定することで再開することが可能です。
    • ユーザーが明示的に指定しない限りこの状態へは遷移しない
  • DELETED
    • Docker Container は明示的に削除を行わない限り停止した状態で残り続ける
    • docker rm <CONTAINER ID>で明示的に削除するとDELETEDの状態へ遷移し、削除される

入門docker 復習(2)

コンポーネント

image

Docker Imageとは

  • Imageは環境のスナップショット
    • CentOSUbuntuやAlpineなどのOS
    • NginxやMySQLのようなソフトウェア
    • PHPRubyのようなランタイムなどの環境
  • DockerImageはDockerの公式がDockerHubというサービス上で様々なOS・ソフトウェアを公開しており、取得可能。 $ docker pull ubuntu #ubuntuを取得する
    $ docker run ruby ruby -e 'puts "Hello, Docker!" #rubyを実行し、"Hello, Docker!"を表示する
  • tagを指定することで特定のバージョンを使用することができる $ docker run python:2.7 python --version #pythonの2.7を実行し、verを表示する

dockerfile

Dockerfile

  • DockerImage(スナップショット)の作成はDockerfileを記述し、ビルドして行う。

  • ローカルにあるDockerfile確認コマンド
    $ docker images

  • Docker Image のビルド&実行
    $ docker build -t hello .
    $ docker run hello

Docker Hub へアップロード

  • ローカルで開発したイメージをステージングや本番環境で動かすにはDockerレジストリにアップロードする必要がある。
  • DockerレジストリはDockerImageを保存するための場所で、Docker版のGitHubのようなもの。

  • Docker Hubへログイン
    $ docker login

  • Docker Image の命名
    • Docker Hub にアップロードするためにはDockerHubのDockerImageの命名規則に則る必要がある。
      $ docker tag hello <USER NAME>/<IMAGE NAME>
  • Docker Imageのアップロード
    $ docker push <USER NAME>/<IMAGE NAME>
  • Docker Hub の確認
  • DockerHubにアップロードしたDockerImageの実行
    • 同名のイメージがある場合はpullできないため、事前に削除する
      $ docker pull <USER NAME>/<IMAGE NAME>
      $ docker run <USER NAME>/<IMAGE NAME>

DSL

基本的なコマンド

  • FROM
    • ベースとなるDockerImageを指定
    • Dockerイメージの上にCOPYやRUNのコマンドを重ねて作成する
    • 公式で提供されているImageを使用するのが一般的
    • ここで設定したイメージを「ベースイメージ」と呼ぶ
      FROM node
  • ENV
    • Docker内で使用する環境変数
    • Dockerの起動時にデフォルトで定義されていてほしい環境変数を定義すると良い
      ENV NODE_ENV=production
  • WORKDIR
    • Dockerfileでコマンドを実行する際に基準となるディレクトリを設定する
    • このとき存在しないディレクトリを指定すると自動的にディレクトリが作成される
    • デフォルトだと / が設定されているため、最悪の場合既存のディレクトリを上書きしてしまいコンテナが起動しなくなる
      WORKDIR /scripts
  • COPY

  • RUN

    • Docker内でコマンドを実行
    • コンテナへ依存するライブラリやパッケージのインストールやユーザーの設定などの処理を実行
      RUN npm install \ && groupadd app \ && useradd -g app app \ && chown -R app:app /scripts
  • USER
    • 作成したDockerImage起動時にログインするユーザーを指定
    • デフォルトは root が設定されているため、セキュリティリスクを回避するために別のユーザーを指定する方が良い
      USER app
  • CMD
    • Docker起動時にデフォルトで実行されるコマンドを定義
    • Dockerはここで設定したコマンドがフォアグラウンドで実行されている間が生存期間になる
    • プロセスの処理が走っている間はフォアグラウンドで実行するように記述(バックグラウンドで起動するとDockerが終了してしまう)
      CMD ["npm", "run", "start"]

よく使用されるコマンド

  • EXPOSE

    • コンテナ起動時に公開することを想定されているポートを記述
    • 他人がどのポートを使用するかわかるため、記述すると丁寧
    • コンテナ起動時に EXPOSE で指定されたポートをホスト側へ公開するには -P オプションを使用する必要がある
      EXPOSE 3000
      $ docker run -P nginx
  • VOLUME

    • Data Volumeを作成するためのコマンド
    • 永続的なデータや共有するためのデータ、更新頻度の激しいファイルを扱うために使用
    • 永続的なデータはDockerで管理することは推奨されないため、ログのような更新頻度の激しいファイルで使用すると良い
      VOLUME ["/app/log"]
  • ARGS

    • Dockerfileのビルド時に変数を使用するためのコマンド
    • ビルドの前提条件/必要情報が増えると複雑化につながるため、基本的に使用しない方が良い
      ARGS ${node_env:-production} ENV node_env
      $ docker build --build-arg node_env=development .
  • ADD

    • COPY コマンドを拡張したコマンド
    • 主に以下の3つの機能を持つ

      1. COPY と同じく指定したパスをコンテナ内へコピー
      2. URLを指定した場合、そのURLからファイルをダウンロードし、コンテナ内へコピー
      3. コピーされたパスが .tar もしくは .tar.gz の場合解凍する
    • 基本的に ADD を使うのは避け、 COPY を使うのが良い

      • ADD は「指定したファイルのコピー」・「指定したURLの取得 」・「圧縮されたファイルの解凍」と高機能な反面、Dockerfileの複雑度が増す
      • URLからファイルを取得するのはパブリックへ依存が発生し、URLの参照先が変更された際にビルド不可なDockerfileができる
      • COPY の場合機能がシンプルなため、シンプルなDockerfileの作成に繋がる
  • ENTRYPOINT

    • 指定されたコマンドを実行
    • CMDとは異なり、 docker run 時に指定したコマンドを ENTRYPOINT の引数として使用
      ENTRYPOINT ["echo"] #引数に "hello" を渡すと echo "hello" が実行される
      $ docker run <IMAGE NAME> "hello!" hello!
      $ docker run --entrypoint date <IMAGE NAME> #entrypoint は実行時のオプションで変更可能

    • 基本的に CMD を使うのが良い

      • ENTRYPOINT はDocker起動時のコマンドを強制する
      • 一般的なWebアプリケーションの場合は CMD を使用する方がユーザーにとって使いやすいDocker Image になる

入門docker 復習(1)

はじめに

Dockerとは

  • コンテナと呼ばれる仮想化技術

なぜDockerを使うのか

  • ポータビリティ
    • 特定の環境をパッケージし、どの環境でも動くポータビリティを保証する
    • 任意の状態をスナップショットとして保存し、他の開発者や環境へ配布が可能
  • オーバヘッド(付加的な処理)
    • Linuxカーネルの機能を利用しているため、VMと比較して仮想化レイヤーが少ない。
    • VMより少ないオーバヘッドで環境構築できる
  • Immutable Infrastructure(不変なインフラ)
    • 今まではライブラリの更新・コードの追加をする際はサーバーへの操作で変更を加えてきた
    • 変更が発生する場合は新しくスナップショットを保存し、サーバーを立ち上げる
    • Dockerfileによりインフラをコードベースで構築し、Imageによりスナップショットとして保存する

VMとDocker

  • VMはコンピュータ自体を仮想化する一方、Dockerはプロセスを仮想化する。

VirtualMachine

  • VirtualMachineは、ハードウェア・カーネル(OS)・ユーザースペースの低レイヤーから仮想化をする技術
  • 仮想化領域が広くなる分、オーバヘッドが大きくなる

Docker

  • Dockerはコンテナと呼ばれる仮想化技術。
  • コンテナはLinuxカーネルの機能を用いた技術で、以下の機能を組み合わせて実現している。
    • cgroup
      • 計算リソースを隔離し、コンテナへリソースの割り当てと制御を行う。
    • namespace
      • プロセスやネットワークなど複数の種類のリソースを隔離する。
    • Capability
      • スーパーユーザーの機能を制限、管理する機能。
  • ホストOSとリソースを共有・使用し、高速かつ軽量な仮想化を実現している。

【MySQL】rootのパスワードを変更する

  • mysqlを停止し、セーフモードでログイン
$ mysql.server stop
$ mysqld_safe --skip-grant-tables &
$ mysql -u root
  • パスワードをnullに設定する
mysql > UPDATE mysql.user SET authentication_string=null WHERE User='root';

mysql > exit;
  • mysqlを再起動し、パスワードを再設定
$ mysql.server stop
$ mysql.server start
$ mysql -u root

mysql > USE mysql;
mysql > ALTER USER 'root'@'localhost' identified BY 'password';

mysql > exit;
  • パスワードが設定されたか確認
$ mysql.server stop
$ mysql.server start
$ mysql -u root -p
password:  //設定したパスワードを入力