こんにちは,米国データサイエンティストのかめ(@usdatascientist)です.
Docker超入門第5回です.今回はついにDockerfileを使ってDocker imageをビルドしてみます!
実業務ではこのDockerfileを使ってDocker imageやコンテナを作ることが多く,DockerfileをメンテすることがDockerを使いこなすことに繋がります.(*なので一番重要)
Dockerfileは学ぶことがたくさんありますが,今回は「とりあえず使ってみる」ってとこまで.
「とりあえず使ってみる」のは簡単なのでサクッとやってみましょう!
前回の記事をまだ読んでない人はこちら↓
(追記:Docker動画講座作りました.Dockerについてもっと学びたい人は是非!14時間にも及ぶ超壮大講座です.
目次
Dockerfileってなんだっけ?
DockerfileはDocker imageの設計図で,DockerfileをビルドすることでDocker imageを作成できます.
そう.今回はDocker Hubにあるものを使うのではなくて,Dockerfileからビルドして作ってみます.
DockerfileはDocker imageを作るための設計図のようなもので,1行に1コマンドが記載されているテキストファイルです.
例えば「◯◯をインストールする」とか「△△のファイルを作成する」と言った具合にそのDocker imageがどういう手順で作られるのかがわかるようになっています.
これがDockerfileだ!
2020年1月現在のubuntu:latest(version18.04)のDockerfileはこちらです.(大抵Docker Hubのリポジトリにリンクがあります.) (Versionが変わっている場合は最新(lastetタグ)のDockerfileをみてください.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
FROM scratch ADD ubuntu-bionic-core-cloudimg-amd64-root.tar.gz / # verify that the APT lists files do not exist RUN [ -z "$(apt-get indextargets)" ] # (see https://bugs.launchpad.net/cloud-images/+bug/1699913) # a few minor docker-specific tweaks # see https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap RUN set -xe \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L40-L48 && echo '#!/bin/sh' > /usr/sbin/policy-rc.d \ && echo 'exit 101' >> /usr/sbin/policy-rc.d \ && chmod +x /usr/sbin/policy-rc.d \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L54-L56 && dpkg-divert --local --rename --add /sbin/initctl \ && cp -a /usr/sbin/policy-rc.d /sbin/initctl \ && sed -i 's/^exit.*/exit 0/' /sbin/initctl \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L71-L78 && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L85-L105 && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \ && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \ && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L109-L115 && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L118-L130 && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \ \ # https://github.com/docker/docker/blob/9a9fc01af8fb5d98b8eec0740716226fadb3735c/contrib/mkimage/debootstrap#L134-L151 && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests # make systemd-detect-virt return "docker" # See: https://github.com/systemd/systemd/blob/aa0c34279ee40bce2f9681b496922dedbadfca19/src/basic/virt.c#L434 RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container CMD ["/bin/bash"] |
その通り!ubuntuのDocker imageはこれらのコマンドが実行されて作られたものなんですね.
Dockerfileを作成しビルドしてみよう
それでは,まだDockerfileの中身についてはあまりわかってないけど,試しに自分でDockerfileを作ってビルドしてみよう!
dockerフォルダを作成し,その中にDockerfileというファイルを作ります.
1 2 3 4 |
Desktop (🐢 ) :$ mkdir docker Desktop (🐢 ) :$ cd docker/ docker (🐢 ) :$ touch Dockerfile docker (🐢 ) :$ subl Dockerfile |
私は ~/Desktop に作りました. $subl コマンドでSublimeでDockerfileを開き,以下のコードをコピーしてください.(どのエディタでも構いませんが,本ブログではSublimeの使用を進めています.Sublimeについてはこちら. $subl コマンドが動かない人は正しくPathが通っていないので,こちらの記事のsublime使い方④を参考にしてください.sublimeは必須ではないので,他のエディタでももちろん問題ないです)
1 2 |
FROM ubuntu:latest RUN touch test |
- FROM ubuntu:latest ベースになるDocker image
- RUN touch test ubuntu:latest の上に $ touch test を実行したimage layerを作成
それでは,Dockerfileをビルドしてみましょう.Dockerfileが保存されているフォルダに移動し, $ docker build . でビルドします.
するとDockerはカレントディレクトリのなかにあるDockerfileというファイルを探してビルドします.
– 今回はDockerfileを保存したフォルダに移動しましたが,.(カレントディレクトリ)の代わりにpathを指定する場合もあります.(が,少しイレギュラーなので次回の記事で)
– Dockerfileという名前ではないDockerfileを使う場合は -f optionでファイル名を指定します.が,基本はDockerfileという名前にするのが一般的です.
1 2 3 4 5 6 7 8 9 10 |
~ (🐢 ) :$ cd Desktop/docker/ docker (🐢 ) :$ docker build . Sending build context to Docker daemon 69.63kB Step 1/2 : FROM ubuntu:latest ---> 549b9b86cb8d Step 2/2 : RUN touch test ---> Running in 464232daec6a Removing intermediate container 464232daec6a ---> 46e8b7ef60ea Successfully built 46e8b7ef60ea |
最後に出力されたIDがimage IDです.(ここでは 46e8b7ef60ea ) $ docker image コマンドでimageリストをみると,確かに新しいimageが作成されているのがわかると思います.
1 2 3 |
docker (🐢 ) :$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 46e8b7ef60ea 5 minutes ago 64.2MB |
ビルドしたimageをrunしてコンテナに入る
runしてコンテナに入ってみましょう.名前がないので今回はIDを指定します.
1 2 3 |
docker (🐢 ) :$ docker run -it 46e8b7ef60ea bash root@af222d93638b:/# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var |
ちゃんとtestファイルがあることがわかりますね!
前回までの記事では,pullしてきたimageをrunしてコンテナに入り, $touch test を実行して test ファイルを作成しました.
しかし,今回の記事ではDockerfileにRUN touch testを記述することで test ファイルを作成しています.
基本的にこの二つのやり方
- コンテナを直接更新
- Dockerfileを更新
でDockerコンテナをどんどん更新していきますが,実業務ではなるべく「Dockerfileを更新」するようにしましょう.そうすることで,そのコンテナがどういうコンテナなのかがわかります.
今回の例では「このDockerコンテナはubuntuのimageにtestというファイルを作ったコンテナなんだな」とわかるわけです.
Dockerfileは最後の行に付け加えて更新していく
もうお気付きの通り,Dockerfileに記述された各行は各image layerに値します.
既にそのlayerがローカルにある場合は新しく作らず使い回すという話をしました.
そのため,基本はDockerfileを更新する際には最後の行に新しい命令文を追加していきます.
なぜなら途中の行を変えると,そのあとの行のlayerは全て新しいものとみなされ再度layerが作成されます.
Dockerfileが大きくなると実行するのに時間がかかり,コンテナを更新するたびにrunするので毎回時間がかかってしまいます.
そのため,基本は最後の行に付け足していって,時間があるときに綺麗にするようにしましょう.
まとめ
さて,今日はDockerfileをビルドしてimageとコンテナを作りました.
- DockerfileはDocker imageを作成するための設計図のようなもの
- コンテナを更新するときはなるべくDockerfileをメンテする
- Dockerfileは基本Dockerfileという名前にする
- Dockerfileを更新するときは最後の行に追加する
- Dockerfileをビルドするには保存されているフォルダに移動し $docker build . を実行する
Dockerのもっとも重要なスキルは「Dockerfileをメンテする」ことです.
いかに自分たちの環境をDockerfileに効率よく綺麗に安全に記せるかが重要になってきます.
なので次回の次回はもっと複雑なDockerfileを作ってみようと思います!では!
追記:第5回書きました.↓ 次回は第1回〜5回で学んだことをまとめます!
[…] まず、Host(コンピュータ)側の任意の場所に、Dockerfileを作成します。今回はDropbox上にdockerという名前のディレクトリを作成してDockerfileを作ります。(例:(Mac) C:UsersuserDropboxdocker 、(Windows)D:DropboxRdocker) […]