ペイの技術MEMO

文系大学生の技術メモ

Docker コンテナの操作

はじめに

前回はDocker イメージ操作をまとめたので、今回はDocker コンテナの操作をまとめます。

gihyo.jp

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ポートで公開していますが、コンテナポートと呼ばれるコンテナ内限定のポートです。

ではどうすれば良いかと言うと、外からきたリクエストをコンテナ内で実行しているアプリケーションまで到達させてあげれば良いです。

f:id:PeeI:20190511113909j:plain

上記に図のように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は上記のようにコンテナの中に入ってファイルを直接いじるようなことより、コンテナの中で生成されたファイルをホストにコピーして確認するようなデバッグ用途で使われます。

また、破棄されていない終了したコンテナに対しても実行できます。