入門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への接続情報や.git
やnode_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種類から定義することが可能
- 1プロセスは1コンテナ、複数コンテナはネットワークを通して通信を行う
volume
volumeについて
- データを永続化するための機能
- コンテナ上で作成されたファイルはライフサイクルの終了と共に消える
- Volumeはデータ保存、永続化のために設計されており、コンテナのライフサイクルとは独立してファイルの管理を行う
volumeType
入門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は環境のスナップショット
- 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 Hubへログイン
$ docker login
- Docker Image の命名
- Docker Hub にアップロードするためにはDockerHubのDockerImageの命名規則に則る必要がある。
$ docker tag hello <USER NAME>/<IMAGE NAME>
- Docker Hub にアップロードするためにはDockerHubのDockerImageの命名規則に則る必要がある。
- 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>
- 同名のイメージがある場合はpullできないため、事前に削除する
DSL
基本的なコマンド
- FROM
- ベースとなるDockerImageを指定
- Dockerイメージの上にCOPYやRUNのコマンドを重ねて作成する
- 公式で提供されているImageを使用するのが一般的
- ここで設定したイメージを「ベースイメージ」と呼ぶ
FROM node
- ENV
- WORKDIR
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つの機能を持つ
- COPY と同じく指定したパスをコンテナ内へコピー
- URLを指定した場合、そのURLからファイルをダウンロードし、コンテナ内へコピー
- コピーされたパスが .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を使うのか
- ポータビリティ
- 特定の環境をパッケージし、どの環境でも動くポータビリティを保証する
- 任意の状態をスナップショットとして保存し、他の開発者や環境へ配布が可能
- オーバヘッド(付加的な処理)
- Immutable Infrastructure(不変なインフラ)
- 今まではライブラリの更新・コードの追加をする際はサーバーへの操作で変更を加えてきた
- 変更が発生する場合は新しくスナップショットを保存し、サーバーを立ち上げる
- Dockerfileによりインフラをコードベースで構築し、Imageによりスナップショットとして保存する
VMとDocker
- VMはコンピュータ自体を仮想化する一方、Dockerはプロセスを仮想化する。
VirtualMachine
- VirtualMachineは、ハードウェア・カーネル(OS)・ユーザースペースの低レイヤーから仮想化をする技術
- 仮想化領域が広くなる分、オーバヘッドが大きくなる
Docker
【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: //設定したパスワードを入力