Dockerで開発環境を作成するメモ1

軽量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つある

  1. docker runでコンテナ展開時に-vオプションで指定する
  2. 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.

dockerfile002

docker for windowsの設定画面を開いて、ドライブを共有選択する。(管理者パスワードも必要)

dockerfile003

再度コンテナ実行すると、正常にマウントされるはず。デフォルトでは読み書き可能である。

> 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