Dockerコンテナ内のファイルをコンテナにログインせずに操作してみた

ulgeekアドベントカレンダーの11日目です。

## 何をする記事なのか
docker execコマンドなどでコンテナにログインすることなく、ホストからDockerコンテナ内のファイルを操作してみます。

## なぜこんなことをしてみようと思ったのか
Dockerコンテナ内で見えるファイルは、実際にホスト上のどこかにあるはずです。具体的にどこにあるのか、ホストからどう見えるのか、ホストでの操作がコンテナ内に反映されるのか、確認したい気持ちが湧いてきます。
ということで、実際に確かめてみます。

## 実行環境
Amazon LinuxにDockerをインストールして検証します。
### バージョン
- Amazon Linux AMI 2017.09
- Docker version 17.06.2-ce

### Dockerインストール手順

```shell-session
$ sudo yum install -y docker
$ sudo service docker start
$ sudo usermod -a -G docker ec2-user # このあと一度ログアウトして再ログイン
```

## 検証の流れ
1. centosのイメージをpullする@ホスト
2. centosのコンテナを起動する@ホスト
3. コンテナ内でファイルを作成する@コンテナ
4. /var/lib/docker以下で、3で作成したファイルを探す@ホスト
5. 4で見つかったファイルに追記する@ホスト
6. 5で追記した内容が見えるか確認する@コンテナ

## 実行したコマンドおよび実行結果
1. centosのイメージをpullする@ホスト

    ```shell-session
    $ docker pull centos
    Using default tag: latest
    latest: Pulling from library/centos
    85432449fd0f: Pull complete
    Digest: sha256:3b1a65e9a05f0a77b5e8a698d3359459904c2a354dc3b25ae2e2f5c95f0b3667
    Status: Downloaded newer image for centos:latest
    ```

2. centosのコンテナを起動する@ホスト

    ```shell-session
    $ docker run -it centos
    ```

3. コンテナ内でファイルを作成する@コンテナ

    ```shell-session
    # echo 'I am in container' > /ulgeek2017.txt
    # ls -lai /
    total 68
     12554 drwxr-xr-x  1 root root  4096 Dec  8 03:27 .
     12554 drwxr-xr-x  1 root root  4096 Dec  8 03:27 ..
    403132 -rwxr-xr-x  1 root root     0 Dec  8 03:08 .dockerenv
    394758 -rw-r--r--  1 root root 11958 Nov 28 16:08 anaconda-post.log
    394759 lrwxrwxrwx  1 root root     7 Nov 28 16:07 bin -> usr/bin
     12722 drwxr-xr-x  5 root root   360 Dec  8 03:08 dev
     12593 drwxr-xr-x  1 root root  4096 Dec  8 03:08 etc
     12940 drwxr-xr-x  2 root root  4096 Nov  5  2016 home
    395056 lrwxrwxrwx  1 root root     7 Nov 28 16:07 lib -> usr/lib
    395057 lrwxrwxrwx  1 root root     9 Nov 28 16:07 lib64 -> usr/lib64
     12939 drwxr-xr-x  2 root root  4096 Nov  5  2016 media
     12933 drwxr-xr-x  2 root root  4096 Nov  5  2016 mnt
     12936 drwxr-xr-x  2 root root  4096 Nov  5  2016 opt
         1 dr-xr-xr-x 95 root root     0 Dec  8 03:08 proc
     12854 dr-xr-x---  2 root root  4096 Nov 28 16:08 root
     12849 drwxr-xr-x 10 root root  4096 Nov 28 16:08 run
    395090 lrwxrwxrwx  1 root root     8 Nov 28 16:07 sbin -> usr/sbin
     12938 drwxr-xr-x  2 root root  4096 Nov  5  2016 srv
         1 dr-xr-xr-x 13 root root     0 Dec  8 03:09 sys
     12931 drwxrwxrwt  7 root root  4096 Nov 28 16:08 tmp
    403287 -rw-r--r--  1 root root    18 Dec  8 03:27 ulgeek2017.txt
     12810 drwxr-xr-x 13 root root  4096 Nov 28 16:07 usr
     12847 drwxr-xr-x 18 root root  4096 Nov 28 16:07 var
    ```

4. /var/lib/docker以下で、3で作成したファイルを探す@ホスト

    ```shell-session
    $ sudo find /var/lib/docker -name ulgeek2017.txt
    /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/merged/ulgeek2017.txt
    /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff/ulgeek2017.txt
    $ sudo ls -lai /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/m
    erged
    total 80
     12554 drwxr-xr-x  1 root root  4096 Dec  8 03:27 .
    403135 drwx------  5 root root  4096 Dec  8 03:08 ..
    394758 -rw-r--r--  1 root root 11958 Nov 28 16:08 anaconda-post.log
    394759 lrwxrwxrwx  1 root root     7 Nov 28 16:07 bin -> usr/bin
     12721 drwxr-xr-x  1 root root  4096 Dec  8 03:08 dev
    403132 -rwxr-xr-x  1 root root     0 Dec  8 03:08 .dockerenv
     12593 drwxr-xr-x  1 root root  4096 Dec  8 03:08 etc
     12940 drwxr-xr-x  2 root root  4096 Nov  5  2016 home
    395056 lrwxrwxrwx  1 root root     7 Nov 28 16:07 lib -> usr/lib
    395057 lrwxrwxrwx  1 root root     9 Nov 28 16:07 lib64 -> usr/lib64
     12939 drwxr-xr-x  2 root root  4096 Nov  5  2016 media
     12933 drwxr-xr-x  2 root root  4096 Nov  5  2016 mnt
     12936 drwxr-xr-x  2 root root  4096 Nov  5  2016 opt
     12719 drwxr-xr-x  2 root root  4096 Nov 28 16:07 proc
     12854 dr-xr-x---  2 root root  4096 Nov 28 16:08 root
     12849 drwxr-xr-x 10 root root  4096 Nov 28 16:08 run
    395090 lrwxrwxrwx  1 root root     8 Nov 28 16:07 sbin -> usr/sbin
     12938 drwxr-xr-x  2 root root  4096 Nov  5  2016 srv
     12725 drwxr-xr-x  2 root root  4096 Nov 28 16:07 sys
     12931 drwxrwxrwt  7 root root  4096 Nov 28 16:08 tmp
    403287 -rw-r--r--  1 root root    18 Dec  8 03:27 ulgeek2017.txt
     12810 drwxr-xr-x 13 root root  4096 Nov 28 16:07 usr
     12847 drwxr-xr-x 18 root root  4096 Nov 28 16:07 var
    $ sudo ls -lai /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff
    total 12
    403137 drwxr-xr-x 2 root root 4096 Dec  8 03:27 .
    403135 drwx------ 5 root root 4096 Dec  8 03:08 ..
    403287 -rw-r--r-- 1 root root   18 Dec  8 03:27 ulgeek2017.txt
    $ sudo cat /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/merged/ulgeek2017.txt
    I am in container
    $ sudo cat /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff/ulgeek2017.txt
    I am in container
    ```

    コンテナ内で作成したファイルが見つかりました！
    ファイルの内容もそのまま見えます。
    `/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/merge` が、コンテナのルートディレクトリで、 `/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff` が、イメージとコンテナの差分のディレクトリのようです。

5. 4で見つかったファイルに追記する@ホスト

    ```shell-session
    $ sudo sh -c "echo 'I am in host and writing merged' >> /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/merged/ulgeek2017.txt"
    $ sudo sh -c "echo 'I am in host and writing diff' >> /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff/ulgeek2017.txt"
    ```

6. 5で追記した内容が見えるか確認する@コンテナ

    ```shell-session
    # cat ulgeek2017.txt
    I am in container
    I am in host and writing merged
    I am in host and writing diff
    ```

    ホストで追記した内容がコンテナから見えました！
    `ulgeek2017.txt` は、コンテナから見えるものも、ホストのmergedディレクトリにあるものも、diffディレクトリにあるものも、実体は同一ファイルのようです。
    実際に、`ls -lai` で表示されている i ノード番号も一致しています。

## まとめ
Dockerコンテナは（非常に極端に言えば）ただのディレクトリのため、ホストからふつうに見ることができ、ファイル操作もできました。

## 補足

### Dockerコンテナの場所を確認する方法

Dockerコンテナの場所は、docker inspectコマンドでも確認できます。

```shell-session
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6600eb4d071c        centos              "/bin/bash"         25 minutes ago      Up 25 minutes                           zen_payne
$ docker inspect 6600eb4d071c
            :
            :
            :
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25-init/diff:/var/lib/docker/overlay2/9f72b86e43ff4301d73171ef6ce6c257bf0692347273b7aa8f290d7d3e290267/diff",
                "MergedDir": "/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/merged",
                "UpperDir": "/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/diff",
                "WorkDir": "/var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25/work"
            },
            "Name": "overlay2"
        },
            :
            :
            :
```

### コンテナを削除するとどうなるか

コンテナを削除すると、ホスト上のコンテナのディレクトリは消えます。

```shell-session
# exit # コンテナからログアウト
exit
$ docker rm 6600eb4d071c
6600eb4d071c
$ sudo ls /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25
ls: cannot access /var/lib/docker/overlay2/e32ec27b9bce498d9d6c5578c3eced310da8ecb70fa335a446f32836864dbb25: No such file or directory
```

コンテナを削除した後もコンテナ内のファイルを永続化しておきたい場合は、ボリュームを使用する必要があります。

## 関連記事
[Where are Docker images stored?](http://blog.thoward37.me/articles/where-are-docker-images-stored/)