Skip to content

Instantly share code, notes, and snippets.

@y-takagi
Last active November 4, 2016 02:02
Show Gist options
  • Save y-takagi/557a579fb788924a566547b1c5112304 to your computer and use it in GitHub Desktop.
Save y-takagi/557a579fb788924a566547b1c5112304 to your computer and use it in GitHub Desktop.
Usefull recipes when using docker

Docker Cookbook

環境は以下。

Host OSDocker version
Ubuntu 16.041.12.3

1. Move storage directory

Dockerは、imageやその他データをデフォルトでは /var/lib/docker に格納する。 ただし、ディスク容量の関係で別の場所に変更したいことがある。その方法をまとめる。

基本的には簡単なことで、docker daemonの起動オプションに

-g /path/to/directory

を与えるだけである。

ただdockerをsystemd経由で起動してる場合は(大半はそうであると思うが)、設定ファイルに書く必要がある。 設定ファイルはデフォルトで lib/systemd/system/docker.service にあるが、 基本は /etc/systemd/system/docker.service.d に別途設定ファイルを置いて反映させる。

# /etc/systemd/system/docker.service.d/options.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -g /path/to/directory

設定ファイルの反映

sudo systemctl daemon-reload
sudo systemctl restart docker

Reference

2. Using user namespace options

ホストのディレクトリをマウントしたコンテナ内で、そのマウントした場所にホストのuid/gidでファイルを作成したいことがある。 そうすることで、開発コードと実行環境を分ける事ができる。

以下では ruby image を用いた簡単な例を示す。

wo/ user namespace

SinatraやRailsのプロジェクトを作成する際にGemfileを用意すると思うが、これをコンテナで生成してみる。

mkdir hello_project && cd hello_project
docker run --rm -w /workdir -v $(pwd):/workdir ruby bundle init

するとホストの /path/to/hello_project に以下のファイルが出来ている。

$ ls -l
合計 4
-rw-r--r-- 1 root root 75 11月  3 16:31 Gemfile

このGemfileはuid/gidがrootのになっているので、ホストで編集する際にはroot権限で扱う必要があり面倒である。

w/ user namespace

user namespaceの機能を使うと、ホストのuid/gidをコンテナのuid/gidにマップすることが出来る。 この機能を使うことで、生成されたGemfileの所有者をホストのuserにすることが出来る。

ホストuserのuid/gidを確認する。

$ id
uid=1000(ubuntu) gid=1000(ubuntu) ...

/etc/subuid と /etc/subgid を編集する。

# /etc/subuid
ubuntu:1000:65536
# /etc/subgid
ubuntu:1000:65536

docker daemonの起動オプションを設定する。

# /etc/systemd/system/docker.service.d/options.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --userns-remap=ubuntu

設定ファイルの反映

sudo systemctl daemon-reload
sudo systemctl restart docker

以上の状態で先程と同じようにGemfileを生成すると、ファイルの所有者がホストuserになっている。

本来user namespaceは、ホストに存在しないuid/gidをコンテナのuid/gidにマップすることでセキュリティレベルを上げるのに利用される。 なので上記の手法は、開発環境でのみ利用すること。

Reference

3. Connect host’s localhost from container

Dockerはインストール時に、docker0という名前の仮想ブリッジを作成する。

$ ip a
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:ce:78:31:14 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:ceff:fe78:3114/64 scope link
       valid_lft forever preferred_lft forever
...

ホストとコンテナはこの仮想ブリッジを通してパケットの送受信が可能なので、 コンテナの起動時にdocker0のipを渡すことで、ホストで起動中の何らかのサーバにアクセスできる。

host_ip=`ip a list docker0 | grep "inet " | awk '{print $2}' | cut -d/ -f1`
docker run -e some_endpoint=$host_ip some_image

4. Alias for one-off command

コンテナでone-offコマンドを実行するためのaliasを設定する。

.bashrc のサンプル

# ~/.bashrc
ruby_cmds=("ruby" "irb" "bundle")
node_cmds=("node" "npm")

declare -A imageCmdsMap
imageCmdsMap=( \
    ["ruby:2.3-slim"]=${ruby_cmds[@]} \
    ["node:6.4.0-slim"]=${node_cmds[@]} \
)

local_images=(`docker images | awk 'NR > 1 {print $1 ":" $2}'`)

for image in ${!imageCmdsMap[@]}; do
    if [[ " ${local_images[*]} " == *" $image "* ]]; then
        cmds=${imageCmdsMap[$image][@]}
        for cmd in ${cmds[@]}; do
            alias $cmd="docker run -it --rm -w /app -v \$(pwd):/app $image $cmd"
        done
        unset cmd
    fi
    unset cmds
done
unset image

上記を .bashrc に設定しておくとホストからコンテナのコマンドを以下のように利用できる。

$ pry
$ bundle install
$ npm install

ただ、カレントディレクトリ以下にないファイルはコマンドに渡せない、ポートの設定などが出来ない等の問題があるので 汎用的には使えない。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment