こんにちは!ともわん(@TomoOne4)です。
僕は、IT企業でマーケティングやセールスをやっています。
Dockerについての第3回目投稿です。
今回は、「Docker HubからpullしてきたUbuntuのコンテナを更新し、それを自分のDocker Hubリポジトリにアップ(push)して、みんなが使えるようにしたら、試しに自分で持ってくる(pull)してみるところまでを扱います。
UbuntuはLunuxのOSですのでこの上でWordPressなども動かす事ができますよ。
今回のポイント
- docker pullでDocker Hubからコンテナを構築
- 構築したコンテナを更新
- 更新したコンテナをdocker pushでDocker Hubの自分のリポジトリに上げる
- 上げたリポジトリから、docker pullでDocker Hubからコンテナを構築
ここで書く内容は、Udemy で受講できる、
かめ れおんさんの米国AI開発者がゼロから教えるDocker講座
で学んだ内容を自分の中で定着するために調べたり考えたりした内容を踏まえて進めていきます。
導入は文章より動画のほうがすっと入ってくる人も多いと思いますので、少し記事を読んでいただき
「Docker面白そうだし、簡単そう」
と思った人はぜひUdemyで米国AI開発者がゼロから教えるDocker講座を受けてみてください。
Dockerやコンテナ、仮想化については第1回、第2回がありますのでこちらをみてみてください!
Ubuntuのコンテナ更新
実際の業務では、
Docker Hubから持ってきた(pullしてきた)Docker Imageを
自分(Host)側で必要なライブラリなどを入れて更新して自分たちが使えるようにしていくという流れを取ります。
第2回をご覧いただいた方ならわかるのですが、イメージレイヤーを追加することです。
その方法としては、次の2つがあります。
【実際の業務でのコンテナ更新方法】
1.コンテナからDocker Imageを更新する方法
2.Docker Fileから更新する方法(こっちのほうが一般的)
Docker Fileから更新する方法は別の記事で扱いますので、今回は、コンテナからDocker Imageを更新する方法を取り上げてみます。
コンテナ(Ubuntu)に入り、ディレクトリを1つ追加(更新)してみる
まずは、ubuntuのコンテナにbashで実行します。
$ docker run -it ubuntu bash
root@9bae5479ddfc:/#
現状のコンテナUbuntuのルートディレクトリ直下を確認してみます。
root@9bae5479ddfc:/# ls -l
total 48
lrwxrwxrwx 1 root root 7 Jul 3 01:56 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Apr 15 11:09 boot
drwxr-xr-x 5 root root 360 Aug 11 23:47 dev
drwxr-xr-x 1 root root 4096 Aug 11 23:47 etc
drwxr-xr-x 2 root root 4096 Apr 15 11:09 home
lrwxrwxrwx 1 root root 7 Jul 3 01:56 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 3 01:56 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4096 Jul 3 01:57 media
drwxr-xr-x 2 root root 4096 Jul 3 01:57 mnt
drwxr-xr-x 2 root root 4096 Jul 3 01:57 opt
dr-xr-xr-x 159 root root 0 Aug 11 23:47 proc
drwx------ 2 root root 4096 Jul 3 02:00 root
drwxr-xr-x 1 root root 4096 Jul 6 21:56 run
lrwxrwxrwx 1 root root 8 Jul 3 01:56 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jul 3 01:57 srv
dr-xr-xr-x 12 root root 0 Aug 11 23:47 sys
drwxrwxrwt 2 root root 4096 Jul 3 02:00 tmp
drwxr-xr-x 1 root root 4096 Jul 3 01:57 usr
drwxr-xr-x 1 root root 4096 Jul 3 02:00 var
ここに Linuxのtouch(ファイルを追加する)コマンドで testというファイルを作成します。
これが、今回の更新内容になります。
※実務ではもっと色々変えていきますが、今回はテストなのでファイル1個追加にとどめておきます。
root@9bae5479ddfc:/# touch test
root@9bae5479ddfc:/# ls -l
total 48
lrwxrwxrwx 1 root root 7 Jul 3 01:56 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Apr 15 11:09 boot
drwxr-xr-x 5 root root 360 Aug 11 23:47 dev
drwxr-xr-x 1 root root 4096 Aug 11 23:47 etc
drwxr-xr-x 2 root root 4096 Apr 15 11:09 home
lrwxrwxrwx 1 root root 7 Jul 3 01:56 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 3 01:56 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4096 Jul 3 01:57 media
drwxr-xr-x 2 root root 4096 Jul 3 01:57 mnt
drwxr-xr-x 2 root root 4096 Jul 3 01:57 opt
dr-xr-xr-x 159 root root 0 Aug 11 23:47 proc
drwx------ 2 root root 4096 Jul 3 02:00 root
drwxr-xr-x 1 root root 4096 Jul 6 21:56 run
lrwxrwxrwx 1 root root 8 Jul 3 01:56 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jul 3 01:57 srv
dr-xr-xr-x 12 root root 0 Aug 11 23:51 sys
-rw-r--r-- 1 root root 0 Aug 11 23:51 test
drwxrwxrwt 2 root root 4096 Jul 3 02:00 tmp
drwxr-xr-x 1 root root 4096 Jul 3 01:57 usr
drwxr-xr-x 1 root root 4096 Jul 3 02:00 var
testファイルが追加されました。
更新ができたので、exitで一度コンテナから抜けます。
root@9bae5479ddfc:/# exit
それでは、イメージを確認してみます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9bae5479ddfc ubuntu "bash" 6 minutes ago Exited (0) 52 seconds ago charming_heyrovsky
すると、作ったコンテナがありますが、STATUSがExitedなので、起動していません。(exitでコンテナを抜けたので、当たり前なのですが・・・)
そこで、起動するために、restartします。
docker restart {Container ID / Container Name}
$ docker restart 9bae5479ddfc
9bae5479ddfc
すると docker ps -aコマンドでもう一度プロセスを見てみると、
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9bae5479ddfc ubuntu "bash" 14 hours ago Up About a minute charming_heyrovsky
STATUSが Up になっているのがわかります。
そこからDocker ContainerのUbuntuの中に入る(bash)場合には、docker execを使います。
docker exec -it <Container Name> bash
すでにコンテナはUpしているので、そのコンテナを指定してEXEC(実行)させるということです。
実行させるプログラムは、その後に指定します。(今回は、bash)
$ docker exec -it 9bae5479ddfc bash
root@9bae5479ddfc:/#
コンテナのUbuntuに入れました。
ちなみに、
Dockerが動いていない状態(Exited)でdocker execコマンドを実行すると、エラーが出ます。
Error response from daemon: Container 9bae5479ddfcd537a8a62125679fc1acecbfbeafb639842b22569e3928bf3e11 is not running
これは、あまり使わない方法ですが、デタッチという方法でコンテナから出ると、プロセスは維持したままコンテナから出られます。
デタッチは、 ctrl + q + p
です。
デタッチしたあとに再度コンテナに入るには、アタッチを行います。
docker attach <Container ID>
$ docker attach 9bae5479ddfc
root@9bae5479ddfc:/#
【exitとデタッチの違い】
exitは、コンテナを抜けるときにプロセスを切ってから抜けるため、Exitedステータスになる。再度コンテナへ入るときには docker restartコマンドを実行する。
デタッチは、コンテナを抜けるときにプロセスを維持したまま抜けるため、Upステータスのままになる。再度コンテナへ入るときにはdocker attachコマンドを実行する。
コンテナをCommitして、Docker Image化
次は、更新したコンテナをcommitしていきます。Gitと同じ感じです。
ドキュメントでは、こう書いてあります。
コンテナのファイル変更や設定を、新しいイメージに収容(commit;コミット)するために便利です。これにより、インタラクティブなシェル上でコンテナをデバッグ用に動かしたり、作業中のデータセットを他のサーバに持っていくため出力したりできます。通常は、イメージを管理するためには、文書化されメンテナンスのしやすい Dockerfile を使うのが望ましい方法です。 詳細はイメージ名とタグについてをご覧ください 。
commit
コマンドはこちらです。
docker commit <Container ID> <New Image Name>
$ docker commit 9bae5479ddfc ubuntu:updated
sha256:4a2d7b4af3079f138657310ada4a6c821af5cccf28dc5cb201f61e7a8fd58249
最後のubuntu:updatedの部分は、リポジトリ名:タグ名を指定しています。
コミットしたら、 docker imagesコマンドでイメージを見てみます。すると、
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZ
ubuntu updated 4a2d7b4af307 38 seconds ago 73.9MB
無事にcommitできているようです!
Docker Hubリポジトリを作成し、別名でDocker Imageを登録、push
Docker Hubのリポジトリは、Docker Hubのサイトに行くといろんなイメージが登録されているのですが その入れ物のことをいいます。
Docker Hubを見るとわかるのですが、基本的にリポジトリはイメージ単位に用意するものとなります。
厳密には、
Repository name:Tag name
となり、このなかのRepository nameの部分をImage nameと呼ぶこともあれば、Tag nameまでを含めてImage nameと呼ぶこともあるようです。
Ubuntuの場合ですと、
library/ubuntu:latest
のこれが、ubuntu の Image nameとなります。
※Tag nameの指定をしないと自動でlatestが入ります。
ここが重要なのですが、
イメージ名とリポジトリ名は同じでなければならないということです!
Docker Hubにリポジトリを作成
Docker Hubにリポジトリを作っていきます。
アカウントを取得している前提でDocker Hubに入ります。
Create a Repositoryをクリックし、リポジトリの名前をつけてCreateするだけで完了です!
今回は、my-first-repoとしています。
作成したDocker Imageをpush
イメージの名前を見て、pushをしていきます。
docker tag <source> <target>
docker tag ubuntu:updated <username>/my-first-repo
詳細に言うと、こうなります。↓
<hostname>:<port>/<username>/<repository>:<tag>
【解説】
<hostname>:<port>・・・Docker Hubの場合は省略できる(デフォルトで は、Docker Hubのregistry1-docker.io)
<username>・・・デフォルトでは、library
<tag>・・・デフォルトでは、latest
Docker Hub以外にpushする時は、正式な指定が必要です。
実際にやってみます。(usernameはxxxxxxxxにしております。)
$ docker tag ubuntu:updated xxxxxxxxx/my-first-repo
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu updated 4a2d7b4af307 11 hours ago 73.9MB
xxxxxxxx/my-first-repo latest 4a2d7b4af307 11 hours ago 73.9MB
同じIMAGE IDで違うレポジトリ名で指定したタグ名のものができているのがわかります。
→ 同じイメージに対して複数のタグが付いているイメージです。
それでは、pushしていきます。
docker push <image name>
$ docker push xxxxxxxx/my-first-repo
The push refers to repository [docker.io/xxxxxxxx/my-first-repo]
d5bd72a8e6b0: Pushed
544a70a875fc: Layer already exists
cf0f3facc4a3: Layer already exists
132bcd1e0eb5: Layer already exists
d22cfd6a8b16: Layer already exists
latest: digest: sha256:6fafbe226353cdc354c293d8cc1e8ccb4d8c8bbdb30c3be0bc562c2548bc0540 size: 1359
すると、5つのDocker Imageレイヤーが用意されていて、そのうちの一番上がpushされているのが見えます。
それ以外のイメージレイヤーはubuntuイメージのレイヤーから利用しているので効率的という話は前回の記事でしました。
Docker Hubに行くと、pushしたことがわかります。
作成したDocker Imageをpull
これで、Docker Hubには上がったのでそこからpullしてみます。
(自分であげたDocker Imageを自分でpullしてくる感じになっていますが、本来は開発しているチームのみんながpullしてくれる想定です。)
そのためには、一度pullするイメージを消してから、pullします。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xxxxxxxx/my-first-repo latest 4a2d7b4af307 11 hours ago 73.9MB
今回は、xxxxxxxx/my-first-repo をpullしてくることをやって見るので、同じ名前のイメージをpullできないため、一度消すという作業を行います。
【イメージの削除】
docker rmi <image name>
$ docker rmi xxxxxxxx/my-first-repo
Untagged: xxxxxxxx/my-first-repo:latest
Untagged: xxxxxxxx/my-first-repo@sha256:6fafbe226353cdc354c293d8cc1e8ccb4d8c8bbdb30c3be0bc562c2548bc0540
消えました!
それではpullしていきます。
コマンドは、Docker HubのTagsの右上にあるコマンドをコピーして貼り付けて実行です。
$ docker pull xxxxxxxx/my-first-repo:latest
latest: Pulling from xxxxxxxx/my-first-repo
Digest: sha256:6fafbe226353cdc354c293d8cc1e8ccb4d8c8bbdb30c3be0bc562c2548bc0540
Status: Downloaded newer image for xxxxxxxx/my-first-repo:latest
docker.io/xxxxxxxx/my-first-repo:latest
それでは、確認していきます。
$docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xxxxxxxx/my-first-repo latest 4a2d7b4af307 11 hours ago 73.9MB
無事に、pullできていることを確認できました。
docker runしてpullしてきたコンテナに入ってみます。
$ docker run -it xxxxxxxx/my-first-repo bash
root@63463f42d2ed:/# ls -l
total 52
lrwxrwxrwx 1 root root 7 Jul 3 01:56 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Apr 15 11:09 boot
drwxr-xr-x 5 root root 360 Aug 13 01:32 dev
drwxr-xr-x 1 root root 4096 Aug 13 01:32 etc
drwxr-xr-x 2 root root 4096 Apr 15 11:09 home
lrwxrwxrwx 1 root root 7 Jul 3 01:56 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 3 01:56 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4096 Jul 3 01:57 media
drwxr-xr-x 2 root root 4096 Jul 3 01:57 mnt
drwxr-xr-x 2 root root 4096 Jul 3 01:57 opt
dr-xr-xr-x 161 root root 0 Aug 13 01:32 proc
drwx------ 1 root root 4096 Aug 11 23:52 root
drwxr-xr-x 1 root root 4096 Jul 6 21:56 run
lrwxrwxrwx 1 root root 8 Jul 3 01:56 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jul 3 01:57 srv
dr-xr-xr-x 12 root root 0 Aug 11 23:51 sys
-rw-r--r-- 1 root root 0 Aug 11 23:51 test
drwxrwxrwt 2 root root 4096 Jul 3 02:00 tmp
drwxr-xr-x 1 root root 4096 Jul 3 01:57 usr
drwxr-xr-x 1 root root 4096 Jul 3 02:00 var
testファイルもありますね。
これで、自分が作ったDocker ImageをDocer Hubにpushして、だれでもpullしてこれることを確認できました!(^^)
まとめ
長くなってしまいましたが、この流れを踏めばpullしてコンテナ更新してpushしてみんなに使ってもらえるという業務に近い流れが分かったかと思います。
ここまでできるとDockerって面白くなってきますね!