Docker コンテナの操作
はじめに
前回はDocker イメージ操作をまとめたので、今回はDocker コンテナの操作をまとめます。
Dockerコンテナの操作
Dockerコンテナとは?
- Dockerイメージを基に作成されたもの
- ファイルシステムとアプリケーションが同梱されている箱のようなもの
Dockerコンテナのライフサイクル
Dockerコンテナは実行中・停止・破棄という3つの状態に分類されます。
同じDockerイメージから作成されたDockerコンテナはそれぞれ個別に状態をもちます。
実行中
docker container run
でDockerイメージを基にコンテナが作成され、Dockerfileの内容を基にアプリケーションが実行を開始する- 上記の状態がDockerコンテナは実行中であるということ
停止
docker container stop
かコンテナで実行されているアプリケーションが正常・異常を問わず終了した場合に停止する- 停止してもディスクにはコンテナ終了時の状態が保持されている
破棄
- 破棄しないかぎりホストOSを終了させてもディスクに残り続ける
- 実行・停止を繰り返す度ディスクを専有するので不要なコンテナは破棄する
- 完全に同じ状態をもったコンテナを新しく作成することは不可能(コンテナが開始した時間、実行時間等)なため破棄する際は注意が必要
コンテナの作成と実行
docker container run
はライフサイクルにおいて実行中の状態にするために使います。
docker container run [options] イメージ名[:タグ名] [コマンド] [コマンド引数...]
docker container run [options] イメージID [コマンド] [コマンド引数...]
Dockerはサーバーアプリケーションで利用することが多い為、バックグラウド、ポートフォワーディングできるようにするコマンドが多くなります。
バックグラウンド
docker container run -d example/echo:latest
-d
オプションでバックグラウンドでコンテナを実行できます。
ポートフォワーディング
Dockerコンテナは仮想環境ですが、外から1つの独立したマシンのように扱えます。
少し理解するのに時間がかかったので簡単なFlaskのアプリを使って説明したいと思います。
main.py
下記はホスト0.0.0.0のポート5000で動くFlaskのアプリです。/
にアクセスするとHello World!
と返します。
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Hello world!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
ではhttpieを使って確認してみます。
http localhost:5000 HTTP/1.0 200 OK Content-Length: 12 Content-Type: text/html; charset=utf-8 Date: Sat, 11 May 2019 02:21:00 GMT Server: Werkzeug/0.15.2 Python/3.7.2 Hello world!
そしたらDockerfileを書いてDockerコンテナで動かしてみます。
Dockerfile
FROM python:3.7-slim RUN mkdir /echo RUN pip install flask COPY main.py /echo CMD ["python3", "/echo/main.py"]
docker image build -t example/echo .
docker container run -d example/echo
上記のコマンド2つでDockerfileを基にイメージの作成と、コンテナの起動を行ってます。
そしたら確認してみます。
http localhost:5000 http: error: ConnectionError:
コネクションエラーがおきました。
これはポートの5000番にアクセスできないということです。
なぜかと言うと上述のようにDockerは独立したマシンのように扱える特徴があるので、Flaskで作ったアプリは5000ポートで公開していますが、コンテナポートと呼ばれるコンテナ内限定のポートです。
ではどうすれば良いかと言うと、外からきたリクエストをコンテナ内で実行しているアプリケーションまで到達させてあげれば良いです。
上記に図のようにDockerコンテナ内は5000で公開しているのでそのコンテナに8080でアクセスできるように紐付けます。
docker container run -d -p 8080:5000 example/hello
-p
オプションでポートフォワーディングをしている- -p {ホスト側のポート}:{コンテナポート}と指定する
確認します。
http localhost:8080 HTTP/1.0 200 OK Content-Length: 12 Content-Type: text/html; charset=utf-8 Date: Sat, 11 May 2019 02:52:24 GMT Server: Werkzeug/0.15.2 Python/3.7.3 Hello world!
名前付きコンテナ
docker container ls
でコンテナ一覧を確認するとNAMESに適当な名前が自動でつけられます。
コンテナを制御するコマンドを実行する際はコンテナIDかコンテナ名を指定します。
コンテナ名を指定するとなんどもコンテナIDを調べる必要がなくなり開発効率がよくなります。
docker container run --name [コンテナ名] [イメージ名]:[タグ]
コンテナの一覧
docker container ls
は実行中のコンテナ、終了したコンテナ一覧を表示するためのコマンドです。
docker container ls [options]
下記は項目の意味
項目 | 内容 |
---|---|
CONTAINER ID | コンテナに付与される一意のID |
IMAGE | コンテナ作成に使用されたDockerイメージ |
COMMAND | コンテナで実行されているアプリケーションのプロセス |
CREATED | コンテナが作成されてから経過した時間 |
STATUS | Up(実行中)、Exited(終了)といったコンテナの実行状態 |
PORTS | ホストのポートとコンテナポートの紐付け(ポートフォワーディング) |
NAMES | コンテナにつけられた名前 |
コンテナIDだけ抽出する
docker container ls -q
filterを使う
docker container ls
の結果を条件の一致したもののみ抽出するには下記のコマンドをつかいます。
docker container ls --filter "filter名=値"
filter名で指定するものは多いので下記を参考
ps — Docker-docs-ja 17.06.Beta ドキュメント
終了したコンテナを取得する
docker container ls -a
コンテナの停止
実行しているコンテナを終了するにはdocker container stop
コマンドを実行します。
docker container stop コンテナIDまたはコンテナ名
コンテナの再起動
一度停止したコンテナは破棄しない限り、docker container restart
コマンドで再実行できます。
docker container restart コンテナIDまたはコンテナ名
コンテナの破棄
上述のコンテナのライフサイクルで述べたようにdocker container stop
ではディスクにコンテナが残っているので完全に破棄するにはdocker container rm
コマンドを使用します。
docker container rm コンテナIDまたはコンテナ名
実行中のコマンドは破棄できないので、停止して破棄する以外に-f
オプションをつけることで実行中のコンテナを停止・削除まで行うことができます。
停止の際にコンテナを破棄する
docker container run --rm
は停止時にコンテナを破棄します。
標準出力の取得
下記のコマンドは実行している特定のDockerコンテナの標準出力を表示できます。
docker container logs [options] コンテナIDまたはコンテナ名
実行中コンテナのコマンド実行
Dockerコンテナの中で任意のコマンドを実行するには下記のコマンドを実行します。
docker container exec [options] コンテナIDまたはコンテナ名 コンテナ内で実行するコマンド
標準入力を開いたままにする-i
オプションと、仮想ターミナルを割り当てる-t
オプションを組み合わせると、コンテナをシェル経由で操作できます。(本番環境では注意が必要)
docker container exec -it 36a00a9fddc8 sh # pwd /
ファイルのコピー
docker container cp
コマンドはコンテナ間、コンテナ・ホスト間でファイルをコピーする際に使います。
docker container cp [options] コンテナIDまたはコンテナ名:コンテナ内のコピー元 ホストのコピー先
docker container cp [options] ホストのコピー元 コンテナIDまたはコンテナ名:コンテナ内のコピー先
例えばホストにあるhoge.txt
をコンテナにコピーする際は以下のようにします。
docker container cp hoge.txt 36a00a9fddc8:/tmp
コンテナの中に入って確認してみます。
docker container exec -it 36a00a9fddc8 sh # ls bin boot dev echo etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # cd tmp # ls hoge.txt
次は逆にコンテナにあるfoo.txt
をホストにコピーします。
コンテナ内でfoo.txt
ファイルを作って抜けた後ホストで確認しています。
docker container exec -it 36a00a9fddc8 sh # cd tmp # ls hoge.txt # touch foo.txt # ls foo.txt hoge.txt
ls Dockerfile foo.txt hoge.txt main.py
docker container cp
は上記のようにコンテナの中に入ってファイルを直接いじるようなことより、コンテナの中で生成されたファイルをホストにコピーして確認するようなデバッグ用途で使われます。
また、破棄されていない終了したコンテナに対しても実行できます。