軽量Linux Alpineのコンテナ作成
以下のようなDockerfileを用意して、イメージを作成してみる。
FROM alpine:3.10
ENV HOME=/home/share
WORKDIR $HOME
ベースはalpine:3.10
で、/home/share
というフォルダを作成して、イメージ名alpine_test
、タグ名1.0
としている。元となるalpineのイメージがダウンロードされて、そこからalpine_testが生成される。
> docker build -t alpine_test1:1.0 .
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine_test1 1.0 617923d08bcd 7 seconds ago 5.55MB
alpine 3.10 965ea09ff2eb 6 weeks ago 5.55MB
バックグラウンドでイメージalpine_test1からコンテナ展開する。(名前をalpine01としている)
> docker run -it -d --name alpine01 617923d08bcd
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a41b6e5ac78 617923d08bcd "/bin/sh" 18 seconds ago Up 17 seconds alpine01
展開したAlpineのコンテナ内に入ってみる。指定するシェルは/bin/ash
か/bin/sh
を指定する。最低限のコマンドしかないことがわかる。
> docker exec -it alpine01 /bin/ash
/home/share # cd /bin
/bin # ls
arch conspy ed gunzip linux32 mktemp ping rmdir su zcat
ash cp egrep gzip linux64 more ping6 run-parts sync
base64 date false hostname ln mount pipe_progress sed tar
bbconfig dd fatattr ionice login mountpoint printenv setpriv touch
busybox df fdflush iostat ls mpstat ps setserial true
cat dmesg fgrep ipcalc lzop mv pwd sh umount
chgrp dnsdomainname fsync kbd_mode makemime netstat reformime sleep uname
chmod dumpkmap getopt kill mkdir nice rev stat usleep
chown echo grep link mknod pidof rm stty watch
# git
/bin/ash: git: not found
このコンテナ内にパッケージを追加するには、Alpineの場合だとapk
コマンドを使う。最初にapk update
でリポジトリを取得しておく必要がある。試しにGitをインストールしてみる。
# apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
v3.10.3-71-g50e386f088 [http://dl-cdn.alpinelinux.org/alpine/v3.10/main]
v3.10.3-68-ge1e42c5d6c [http://dl-cdn.alpinelinux.org/alpine/v3.10/community]
OK: 10341 distinct packages available
# apk search git
git-bash-completion-2.22.0-r0
git-cvs-2.22.0-r0
libgit2-0.27-0.27.8-r0
libgit2-dev-0.28.2-r0
perl-git-svn-2.22.0-r0
gitolite-3.6.11-r0
git-2.22.0-r0
git-daemon-openrc-2.22.0-r0
:
# apk add git
(1/6) Installing ca-certificates (20190108-r0)
(2/6) Installing nghttp2-libs (1.39.2-r0)
(3/6) Installing libcurl (7.66.0-r0)
(4/6) Installing expat (2.2.8-r0)
(5/6) Installing pcre2 (10.33-r0)
(6/6) Installing git (2.22.0-r0)
Executing busybox-1.30.1-r2.trigger
Executing ca-certificates-20190108-r0.trigger
OK: 21 MiB in 20 packages
# git
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
These are common Git commands used in various situations:
start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
:
内部で更新されたコンテナから新しいイメージを作成する
コンテナの中で作業しているときに、追加でアプリをインストールしたり、コンテナ内の設定を変更することはもちろん可能である。この更新されたコンテナは、docker rm {container}
しない限り状態は残るが、後述するマウント設定などdocker run
を再実行しないといけなくなる場合がある。
こういった場合では、今の更新されたコンテナの内容をイメージ内に残す必要がある。このときに使うコマンドがdocker commit
になる。
dockerイメージをリポジトリとしてみたときに、ワーク領域の変更をリポジトリにコミットするのと同じだと考えて問題ないと思う。
docker commit {container} {image}:{tag}
タグを省略すると、自動的にlatest
になる。ubuntu18.04のイメージから作成したコンテナに、gitをインストールしたとして、ここから新しいイメージを作成してみる。
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5981656d4449 843a8c99c998 "/bin/bash" 4 hours ago Up 4 minutes ubuntu01
> docker commit ubuntu01 ubuntu-git:1.0
sha256:383942b88caad90e24b18fa4010b611df6983d1e59146acacdbcbb1476d756fb
> docker images
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-git 1.0 1b4c0b6b0cc4 4 seconds ago 186MB
ubuntu-test01 1.0 843a8c99c998 5 hours ago 64.2MB
ubuntu 18.04 775349758637 4 weeks ago 64.2MB
タグだけバージョンアップしてもイメージは別のファイルになるだけだと思われる(タグ名はべつに番号じゃなくてもよい)
ホストのディレクトリをマウントする方法
やり方は2つある
docker run
でコンテナ展開時に-v
オプションで指定するdocker-compose
コマンドで指定するdocker-compose.yml
で指定する
Dockerfile
で指定することはできない。もしできてしまうと、そのイメージを使う場合はマウント元のディレクトリを持っておく必要があるので、意図的にできないようしているらしい。
また、稼働中のコンテナに後でマウントを追加することもできない。この場合は一旦docker commit
して新しいイメージを作成して、今の内容をすべてイメージの保存した後に、再度docker run
してマウントを追加するしかなさそう。
docker run -v {ローカルディレクトリ}:{コンテナ内のマウントパス} -it -d --name={コンテナ名} {イメージ名}:{タグ}
ただし、WSL内のパスはマウントできないので注意すること。
例えばWSLの/home/work
や/mnt/c/Users/hoge/Documents
を/home/work
にマウントしようとしても一見成功したように見えるが、ローカルのファイルとか見えてない。
ローカルのWindows内のフォルダをWSL内で稼働しているdockerコンテナにマウントすることは可能である。パスの表記は以下のようにドライブとかは/c
で記述する。
ドキュメントフォルダ内にあるwork
をマウントしてみる。以下のようなエラーが出る場合、docker for windows
側の共有設定がなされてないのが原因。
> docker run -v /c/Users/hoge/Documents/work:/home/work -it -d --name=dev ae6e75f83dee
docker: Error response from daemon: Drive has not been shared.
docker for windows
の設定画面を開いて、ドライブを共有選択する。(管理者パスワードも必要)
再度コンテナ実行すると、正常にマウントされるはず。デフォルトでは読み書き可能である。
> docker run -v /c/Users/hoge/Documents/work:/home/work -it -d --name=dev ae6e75f83dee
a1b73c99545da8c540339a85f24954d6be1d8be85b03b8bac05970cbced61c2c
> docker exec -it dev /bin/bash
# cd /home/work
# ls
aaa.txt
# cat aaa.txt
hello