⚠️ 記事内に広告を含みます。

dockerコンテナの操作 起動・停止・削除のやり方

dockerコンテナの操作方法について解説します。

dockerコンテナのアタッチとデタッチ

dockerコンテナは意図的に起動したままにしないと停止してしまったりします。

シェルがあるコンテナであれば、起動しているコンテナに入ってシェルを操作できます。これをアタッチと言います。(アタッチはコンテナの標準入出力を手元のコンソールに繋ぐこと)

逆にデタッチはコンテナのシェルから抜けること(コンテナの標準入出力を手元のコンソールから霧花明日こと)です。

実際にアタッチとデタッチを体感してみます。

起動したままのコンテナを作成してアタッチしてみる

##distrolessのイメージのうちシェルを含むdebugイメージ(base-debian11:debug)を起動 -iは--interactiveで標準入力を受け付け、-tはコンテナにttyを割り当て -dはデタッチ
$ docker run -d -it --name debian-base gcr.io/distroless/base-debian11:debug

##起動したコンテナを確認(docker psで出てくるので起動中)
$ docker ps
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS      NAMES
c0cfd74bdb1b   gcr.io/distroless/base-debian11:debug   "/busybox/sh"            5 seconds ago   Up 4 seconds              debian-base

## コンテナにアタッチしてシェルに入る(-dで起動したので今はデタッチ状態)
$ docker attach debian-base

## 以下はdebian-baseのコンテナのシェルを動かしてる
/ # ls
bin      busybox  etc      lib      root     sbin     tmp      var
boot     dev      home     proc     run      sys      usr
/ # pwd
/
# exit
## ↑ exitして抜けるとコンテナが停止する

## docker psだと起動中のコンテナのみ表示 (-aだと停止中も表示)
$ docker ps 
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS      NAMES
docker run -d -it --name debian-base gcr.io/distroless/base-debian11:debug

-dはデタッチ状態で起動(なしではアタッチした状態で起動)

-itは現在のシェルの標準入出力をコンテナにバインド→コンテナ内のシェル(があれば)を操作可能にします。-tで擬似端末を有効化

–nameはコンテナに名前をつける。名前がなくてもCONTAINER IDでコンテナ操作はできる

gcr.io/distroless/base-debian11 → dockerイメージを配布しているdockerHub ホスト名

:debug → base-debian11のバージョン。よくあるのはlatestとか11とかのバージョン識別子

docker runでコンテナを作成した際には指定したベースイメージがなければdocker hubからpullしてイメージをダウンロードしてコンテナを作成、起動してくれます。これはpull create startの一連のコマンドが含まれているからです。

git pullがfetchとmergeをやっているのと同じです。

当然個別に実行しても良いですが、結果は同じになります。

docker startで停止中のコンテナを起動する

##停止を確認
$ docker ps 
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS      NAMES

##docker startで起動する(オプションなしではデタッチ状態で起動)
$ docker start debian-base
debian-base

$ docker ps 
CONTAINER ID   IMAGE                                   COMMAND                  CREATED          STATUS         PORTS                       NAMES
c0cfd74bdb1b   gcr.io/distroless/base-debian11:debug   "/busybox/sh"            15 minutes ago   Up 4 seconds                               debian-base

##アタッチしてみる
### 現環境を確認 → mac
$ sw_vers | head -1
ProductName:		macOS

###アタッチする
$ docker attach debian-base

####コンテナに入ったかを確認する → debianになってる
/ # cat /etc/os-release  | grep -i version=
VERSION="Debian GNU/Linux 11 (bullseye)"

#### Ctrl + qでデタッチ(ダメならCtrl +p, qを押す) (exitしないとデタッチ状態に戻る = 起動したまま)
$ docker ps 
CONTAINER ID   IMAGE                                   COMMAND                  CREATED          STATUS         PORTS                       NAMES
c0cfd74bdb1b   gcr.io/distroless/base-debian11:debug   "/busybox/sh"            27 minutes ago   Up 11 seconds                               debian-base

##おまけ アタッチ状態で停止→起動する
$ docker start -i debian-base

dockerコンテナを停止する

docker attachで入って「exit または Ctrl + C」以外にも停止方法はある

$ docker stop debian-base

## 停止したかどうかをdocker ps -aで確認(statusがexitedになってればOK)
$ docker ps -a
CONTAINER ID   IMAGE                                   COMMAND                  CREATED          STATUS                            PORTS                       NAMES
c0cfd74bdb1b   gcr.io/distroless/base-debian11:debug   "/busybox/sh"            41 minutes ago   Exited (137) About a minute ago                               debian-base

コンテナを削除する

停止したままではコンテナは存在した状態です。

停止で放っておくと、docker ps -aでたくさん出てきて見にくいので
入らなければ削除しましょう

コンテナの削除は dokcer rm で行います。

## 対象はnameでもCONTAINER IDでも良い
$ docker rm debian-base
debian-base

$ docker ps -a
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS      NAMES

イメージも削除する

コンテナを作成した際にベースとなるイメージファイルがローカルに残っています。

コンテナ作成時にいちいちダウンロードすると時間がかかるのでキャッシュしていますが、不要なら削除できます。

## imageを確認してみる latest(通常版)とdebug(シェル有り版)のイメージがある
$ docker images
REPOSITORY                        TAG       IMAGE ID       CREATED        SIZE
gcr.io/distroless/base-debian11   latest    421767200b8f   2 days ago     17.3MB
gcr.io/distroless/base-debian11   debug     ba51ed56693b   2 days ago     18.6MB

## imageの削除
$ docker rmi ba51ed56693b

## 確認 → debugのイメージが消えてる
$ docker images
REPOSITORY                        TAG       IMAGE ID       CREATED        SIZE
gcr.io/distroless/base-debian11   latest    421767200b8f   2 days ago     17.3MB

停止と同時に削除する

コンテナは停止状態でずっと取っておくようなものでもないため、
停止と同時に削除したいことも多いです。

そんな時は起動時にrmオプションをつけておくと良いです。

## --rmオプションを入れて起動する
$ docker run --rm -it --name debian-base gcr.io/distroless/base-debian11:debug 
Unable to find image 'gcr.io/distroless/base-debian11:debug' locally
debug: Pulling from distroless/base-debian11
5f80a38cb015: Already exists 
a839fcbfad1b: Already exists 
4f70717a8bb3: Pull complete 
Digest: sha256:db70d0593de8052385f9c0d0980fa9d5256d9b41d934f0f77f6fa08669747d32
Status: Downloaded newer image for gcr.io/distroless/base-debian11:debug
8879fde70135e04a7dfd48e3473a3b5fffd043eec84cbc0d6abde2fd8e6c679f

## コンテナのシェルでexitして停止する
/ # exit

## docker psで見ると停止中のコンテナはない→削除されてる
$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED       STATUS       PORTS                       NAMES

## imageは削除されずに残るので、イメージ削除は別途必要
$ docker images
REPOSITORY                        TAG       IMAGE ID       CREATED        SIZE
gcr.io/distroless/base-debian11   latest    421767200b8f   2 days ago     17.3MB
gcr.io/distroless/base-debian11   debug     ba51ed56693b   2 days ago     18.6MB

コンテナで実行する(コマンドを実行する)

コンテナ内の実行ファイルを実行する方法としては
1. docker run時にコマンドを指定する (docker run -it –name debian-base gcr.io/distroless/base-debian11:debug)
2. 起動中にexecで起動する

方法があります。

起動中にexecコマンドで起動する方法

起動中のコンテナ(debian-base)中のシェルを起動してみます。

$ docker exec -it debian-base /busybox/sh
/ # 
/ # exit

## ここでexitしてもコンテナは終了しない(起動したシェルを閉じただけなので)

## debian-base(buxybox)には/bin/bashがない。あればそっちを実行してOK

$ docker exec -it ubuntu /bin/bash
/ # echo $SHELL
/bin/bash

上の例のようにコンテナの中に入り込んでシェルを起動して操作することはよくあると思います。

execで起動した場合はexitしてもシェル終了だけでOKですが、docker runで起動したコンテナに対してattachしてシェル操作を行なっている時に流れで「exit」してしまうとコンテナが終了してしまいます。

あっさりと意図せずにコンテナを停止してしまうことになるので、運用中のコンテナをいじる場合は注意しましょう。

dockerコマンドのオプション

docker runやdocker createコマンドにオプションをつけると様々な設定ができます。

代表的なオプションを載せます。

  • –name ContainerName → コンテナの名前をつける
  • –env EnvVar → 環境変数を追加
  • –ip ***.***.***.*** → IPアドレスの追加
  • –mount /mount/point → ファイルシステムのマウント
  • -i → アタッチ済みで起動
  • -t →tty割り当て
  • –rm → コンテナ終了時にコンテナ削除
  • -p 9800:8080 →ホストの9800をコンテナの8080にバインド

コンテナの中身の詳細を確認する

inspectでコンテナの詳細情報を確認できます

$ docker container inspect {containername}

コンテナにファイルをコピーする docker cp

コンテナ内にホストのファイルをコピーする方法はいくつかあります。

  1. dockerfileでCOPYで記述する
  2. docker cpコマンドでコピーする
  3. バインドマウントやNFSで共有する

起動中のコンテナに対して特に設定変更せずにコピーできるのはdocker cpコマンドを使った方法です、

$ docker cp ./go.mod  golang-container:/go/src/

## ./go.modはホストのカレントディレクトリにあるgo.modファイル(コピー元)
## golong-containerはコンテナの名前
## /go/src/はコンテナ内のコピー先のディレクトリ

ファイルシステムのマウント方法(-vではなく–mountが推奨) データ永続化

ファイルシステムのマウントには-vが従来から使われているが、やや冗長だが–mountが推奨されている

https://matsuand.github.io/docs.docker.jp.onthefly/storage/bind-mounts/

dockerの特性上、永続ボリュームを持たないのが良いとされるが、

・永続ボリュームをもたせたい場合
・はDockerホストのファイルシステムを共有したい
という場合はマウントする。

mountオプションを使ってマウントする

例:

$ docker run -d \
 --name debian-base \
 --mount type=bind,src=$(pwd)/src,dst=/src \
 gcr.io/distroless/base-debian11:debug

type=(bind |volume|tmpfs) マウントのタイプを指定する

  • bind バインドマウント
    • Dockerホスト上にあるディレクトリを共有する
  • volume ボリューム
    • ボリュームをマウントする
  • tmpfs tmpfsをマウント
    • メモリ上のファイルシステムをマウントする(揮発性)

バインドマウントのメリット:ホスト上のファイルを共有できる
バインドマウントのデメリット:ホスト上のファイル有無でコンテナの挙動が変わる

ボリュームマウントのメリット:コンテナに新規のファイルシステムをマウントできる。バックアップしやすく、移行しやすい。おすすめ
ボリュームマウントのデメリット:??

tmpfsのメリット:高速なメモリファイルシステムを利用できる
tmpfsのデメリット:データが非永続

バインドマウント

src/dst マウント元とマウント先の指定

type=bind,src=/var/www/html/,dst=/var/www/
##ホストの/var/www/html/ディレクトリをコンテナ内の/var/www/バインドマウントする

バインドプロパゲーション (bind-propagation=shared,slave,private,rshared,rslave,rprivate)

バインドマウント状態でマウント元またはマウント先で新たにマウントした際にそれが互いに反映されるか無視されるか?を設定できます。
デフォルトはマウント元, 先どちらに新たにマウントしても共有されません(bind-propagation=rprivate)。

参考:バインドプロパゲーションの挙動について

tmpfsをマウントする

tmpfsのマウントの場合はsrcの指定はしない

type=tmpfs,dst=/volume

tmpfsはデフォルトでは無制限に領域を割り当てます。
サイズを指定したい場合は、「tmpfs-size=バイト」を指定します。

type=tmpfs,dst=/volume,tmpfs-size=51200000

ボリュームのマウント

ボリュームをマウントする場合はあらかじめdocker volumeを作成します。

$ docker volume create docker-volume
$ docker volume ls
DRIVER    VOLUME NAME
local    docker-volume

## ちなみに削除は
$ docker volume rm docker-volume

作成したボリュームをマウントする

--mount type=volume,src=docker-volume,target=/volume

## 例
$ docker run -it --name debian-baae --mount type=volume,src=docker-volume,target=/volume gcr.io/distroless/base-debian11:debug
debian-baseという名前のbase-debian11:debugをベースイメージとしたコンテナを作成、docker-volumeというdockerボリュームを/volumeにマウントした状態で起動

src=には作成したdockerボリュームを指定します。

ボリュームのバックアップ(ファイルの書き出し)

dockerボリュームのバックアップはバックアップ用コンテナを立ち上げてtarにまとめることで簡単にできます。
言葉だと分かりにくいので、実際にやってみましょう。

操作概要
・バックアップしたいボリューム:docker-volume ($ docker volume ls | grep docker-volume)
・起動中のdocker-volumeをマウントしたコンテナ名:debian-base (docker ps | grep debian)
・docker-volumeのマウント場所:/volume (debian-baseコンテナの中)
・バックアップ名:backup.tar.gz
・バックアップ保存先:/bakcup (新規コンテナとカレントディレクトリ)

バックアップしたいボリューム(docker-volume)をマウントした起動中のコンテナdebian-baseを–volumes-fromで指定して、新しいデータコピー用の使い捨てコンテナを立ち上げる(run –rm)。
-vでホストのカレントディレクトリ($(pwd))をコピー用のコンテナ/backupにバインドマウントしておく。(コンテナ内の/backup配下にバックアップを作成したらホスト上にもコピーしたいから)
バックアップ用新規使い捨てコンテナ上でバックアップ対象のディレクトリ(/volume)の内容を/backup/配下に作成した後にコンテナを削除する。コンテナを削除しても、ホスト側にもバインドマウントしているのでバックアップファイルは存在しているので問題なし。

##バックアップコマンド
$ docker run --rm --volumes-from debian-base -v $(pwd):/backup busybox tar zcvf /backup/backup.tar.gz /volume

##バックアップが作成されているのを確認する(ホスト上での操作、ただし↑でrun立ち上げたコンテナはすでに削除されている(--rm)
$ pwd
bakcup.tar.gz
## tarファイルを解凍
$ tar -xzvf backup.tar.gz
$ pwd
backup.tar.gz  volume/
$ cat volume/newdir/newfiles
this is new files

######## おまけ (↑のnewfilesの準備した方法)##########
###マウントしてるボリュームの存在確認
$ docker volume ls
local docker-volume

### docker-volumeを/volumeにマウントして起動する
$ docker run -it --name debian-baae --mount type=volume,src=docker-volume,target=/volume gcr.io/distroless/base-debian11:debug

##コンテナ内##

/ # ls 
bin      busybox  etc      lib      root     sbin     tmp      var
boot     dev      home     proc     run      sys      usr      volume

/ # mkdir -p volume/newdir && echo "this is new files" > newfiles
/ # cat volume/newdir/newfiles
this is new files

##↑デタッチ##

### debian-baseコンテナの起動確認
$ docker ps 
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS                       NAMES
490826efa2a8   gcr.io/distroless/base-debian11:debug   "/busybox/sh"            6 minutes ago   Up 6 minutes             
###############################################


※volumes-fromは指定したコンテナ同じマウント状態でコンテナを起動する
※ busyboxはUNIXコマンドが入った最低限のシェル環境イメージ(tar cvfを実行する)
※tarコマンドの使い方:tar zcvf バックアップ名.tar.gz 対象ディレクトリ・ファイル

ボリュームの復元

バックアップファイルからボリュームの復元はバックアップしたファイルをコンテナ内でuntarすれば良いです。

$  docker run --rm --volumes-from debian-base -v $(pwd):/backup busybox bash -c "cd /volume && tar xzcf /backup/backup.tar.gz --strip 1"

※ –strip 1はuntarした後に作成されるディレクトリを1階層分無視する。ここでは/volumeの中に/volume/volume/newdir/newfilesというようにvolumeディレクトリが重複するのを回避している。

書き込み制御フラグ readonly (volume,tmpfs,bindで共通)

$ docker --mount type=bind,src=/var/www/html/,dst=/var/www/,readonly

readonlyオプションをつけると読み込み専用になる

コンテナ間のファイル共有方法

作成したコンテナのファイルを教諭したい場合があります。

コンテナ間のデータを共有する方法はいくつかあります。

  1. クラウドストレージサービス S3などを利用する
  2. NFSを利用

vieux/sshfsプラグインのボリュームドライバーを利用する
ssh先のファイルシステムを利用する

nfsはネットワークストレージで同じNFSをコンテナ間で利用すれば、コンテナ間でデータを共有することができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です