コンテナから他サーバをいじってみる

この記事は、[Docker Advent Calendar 2017] (https://qiita.com/advent-calendar/2017/docker)　21日目の記事です。

# 概要
`Docker`のサーバでは許可されていないけど、`Docker`が動いてないサーバで許可されているものを使いたい場合が時々ありますよね？
※人によります。僕にはそんな場合がありました。
そんな場合がいつ起こるかわからないので`sshfs`を使うことで他サーバのファイルをいじってみる。

# 検証内容
sshfs-fromサーバ上のコンテナからsshfs-toサーバのファイルをいじる

# 環境
- OS : CentOS 7.4.1708(Core)

```bash
[root@docker-test centos]# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core)
```

- Docker : 17.09.1-ce

```bash
[root@docker-test centos]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 17.09.1-ce
Storage Driver: overlay
 Backing Filesystem: extfs
 Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 06b9cb35161009dcb7123345749fef02f7cea8e0
runc version: 3f2f8b84a77f73d38244dd690525642a72156c64
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
Kernel Version: 3.10.0-693.11.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.702GiB
Name: docker-test
ID: QDXG:Z7GS:Y5GW:CJCW:RDEY:KCHQ:5ENQ:5CVC:FBLZ:3IZI:MRZA:ZSC6
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Http Proxy: XXXX
Https Proxy: XXXX
No Proxy: localhost,127.0.0.1
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
```

# サーバ情報
- sshfs-to
マウントされる側のサーバ。
sshfs-fromからノンパスで`ssh`が実行できる。

- sshfs-from
マウントする側のサーバ。
sshfs-toへノンパスで`ssh`が実行できる。

# ディレクトリ
- sshfs-to

```bash
[root@sshfs-to sshfs]# tree /tmp/sshfs
/tmp/sshfs
└── sshfs-to.txt

0 directories, 1 file
[root@sshfs-to sshfs]# cat /tmp/sshfs/sshfs-to.txt
sshfs-to
```

- sshfs-from

```bash
[root@sshfs-from Docker]# tree /Docker
/Docker/
├── Dockerfile
├── rsa
│   ├── id_rsa
│   └── known_hosts
└── src
    └── wrapper.sh

2 directories, 4 files
```

## Dockefile

```bash
FROM alpine:latest
MAINTAINER hihihiroro@gmail.com

RUN set -x \
  && http_proxy=XXXX https_proxy=XXXX apk update \
  && http_proxy=XXXX https_proxy=XXXX apk upgrade \
  && http_proxy=XXXX https_proxy=XXXX apk add --no-cache sshfs

ADD rsa/id_rsa /root/.ssh/id_rsa
ADD rsa/known_hosts /root/.ssh/known_hosts

RUN chmod 700 /root/.ssh \
  && chmod 600 /root/.ssh/id_rsa \
  && chmod 644 /root/.ssh/known_hosts \
  && mkdir /sshfs-dir

ADD src/wrapper.sh /usr/local/bin/wrapper.sh
RUN chmod a+x /usr/local/bin/wrapper.sh
CMD ["/usr/local/bin/wrapper.sh"]
```

## wrapper.sh

```bash
[root@sshfs-from Docker]# cat src/wrapper.sh
#!/usr/bin/env sh
# Fail on unset variables and command errors
set -ue -o pipefail

# Prevent commands misbehaving due to locale differences
export LC_ALL=C

echo "## sshfs前確認 : ls -l /sshfs-dir"
ls -l /sshfs-dir

echo "## sshfs : sshfs sshfs-to:/tmp/sshfs /sshfs-dir"
sshfs sshfs-to:/tmp/sshfs /sshfs-dir

echo "## sshfs後確認 : ls -l /sshfs-dir"
ls -l /sshfs-dir

echo "## 書き込み前確認 : ssh sshfs-to ls -l /tmp/sshfs"
ssh sshfs-to ls -l /tmp/sshfs

echo "## 書き込み : touch /sshfs-dir/from_sshfs-from.txt"
touch /sshfs-dir/from_sshfs-from.txt
ls -l /sshfs-dir

echo "## 書き込み後確認 : ssh sshfs-to ls -l /tmp/sshfs"
ssh sshfs-to ls -l /tmp/sshfs
```

# docker image作成
```bash
[root@sshfs-from Docker]# docker build -t sshfs-image .
Sending build context to Docker daemon  8.192kB
Step 1/9 : FROM alpine:latest
 ---> e21c333399e0
Step 2/9 : MAINTAINER hihihiroro@gmail.com
 ---> Running in 07d8189705ab
 ---> e5f8e6074942
Removing intermediate container 07d8189705ab
Step 3/9 : RUN set -x   && http_proxy=XXXX https_proxy=XXXX apk update   && http_proxy=XXXX https_proxy=XXXX apk upgrade   && http_proxy=XXXX https_proxy=XXXX apk add --no-cache sshfs
 ---> Running in b987259de3ef
+ http_proxy=XXXX https_proxy=XXXX apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
v3.7.0-35-g1f6e64f5d4 [http://dl-cdn.alpinelinux.org/alpine/v3.7/main]
v3.7.0-34-g4caa398901 [http://dl-cdn.alpinelinux.org/alpine/v3.7/community]
OK: 9046 distinct packages available
+ http_proxy=XXXX https_proxy=XXXX apk upgrade
Upgrading critical system libraries and apk-tools:
(1/1) Upgrading apk-tools (2.8.1-r1 -> 2.8.1-r2)
Executing busybox-1.27.2-r6.trigger
Continuing the upgrade transaction with new apk-tools:
(1/1) Upgrading busybox (1.27.2-r6 -> 1.27.2-r7)
Executing busybox-1.27.2-r7.post-upgrade
Executing busybox-1.27.2-r7.trigger
OK: 4 MiB in 11 packages
+ http_proxy=XXXX https_proxy=XXXX apk add --no-cache sshfs
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
(1/11) Installing openssh-keygen (7.5_p1-r8)
(2/11) Installing openssh-client (7.5_p1-r8)
(3/11) Installing fuse (2.9.7-r0)
(4/11) Installing libffi (3.2.1-r4)
(5/11) Installing libintl (0.19.8.1-r1)
(6/11) Installing libuuid (2.31-r0)
(7/11) Installing libblkid (2.31-r0)
(8/11) Installing libmount (2.31-r0)
(9/11) Installing pcre (8.41-r1)
(10/11) Installing glib (2.54.2-r0)
(11/11) Installing sshfs (2.10-r2)
Executing busybox-1.27.2-r7.trigger
Executing glib-2.54.2-r0.trigger
OK: 11 MiB in 22 packages
 ---> d65f1420e231
Removing intermediate container b987259de3ef
Step 4/9 : ADD rsa/id_rsa /root/.ssh/id_rsa
 ---> ac2f15cc05f7
Step 5/9 : ADD rsa/known_hosts /root/.ssh/known_hosts
 ---> fb14539d6a09
Step 6/9 : RUN chmod 700 /root/.ssh   && chmod 600 /root/.ssh/id_rsa   && chmod 644 /root/.ssh/known_hosts   && mkdir /sshfs-dir
 ---> Running in ba0cad24c993
 ---> 1fbff8497e17
Removing intermediate container ba0cad24c993
Step 7/9 : ADD src/wrapper.sh /usr/local/bin/wrapper.sh
 ---> c372519234c4
Step 8/9 : RUN chmod a+x /usr/local/bin/wrapper.sh
 ---> Running in feb975f5ab43
 ---> f1dbfcd868cd
Removing intermediate container feb975f5ab43
Step 9/9 : CMD /usr/local/bin/wrapper.sh
 ---> Running in fd4debbcc9ae
 ---> 70a89ed38a86
Removing intermediate container fd4debbcc9ae
Successfully built 70a89ed38a86
Successfully tagged sshfs-image:latest
```

# docker run
```bash
[root@sshfs-from Docker]# docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse -v /etc/hosts:/etc/hosts:ro sshfs-image
## sshfs前確認 : ls -l /sshfs-dir
total 0
## sshfs : sshfs sshfs-to:/tmp/sshfs /sshfs-dir
## sshfs後確認 : ls -l /sshfs-dir
total 4
-rw-r--r--    1 root     root             0 Dec 21 14:29 from_sshfs-from.txt
-rw-r--r--    1 root     root             9 Dec 21 13:18 sshfs-to.txt
## 書き込み前確認 : ssh sshfs-to ls -l /tmp/sshfs
total 4
-rw-r--r-- 1 root root 0 Dec 21 23:29 from_sshfs-from.txt
-rw-r--r-- 1 root root 9 Dec 21 22:18 sshfs-to.txt
## 書き込み : touch /sshfs-dir/from_sshfs-from.txt
total 4
-rw-r--r--    1 root     root             0 Dec 21 14:32 from_sshfs-from.txt
-rw-r--r--    1 root     root             9 Dec 21 13:18 sshfs-to.txt
## 書き込み後確認 : ssh sshfs-to ls -l /tmp/sshfs
total 4
-rw-r--r-- 1 root root 0 Dec 21 23:32 from_sshfs-from.txt
-rw-r--r-- 1 root root 9 Dec 21 22:18 sshfs-to.txt
```
sshfs-fromサーバ上のコンテナから、sshfs-toサーバのディレクトリをマウントしファイルの読み書きができている。
※コンテナから`sshfs`コマンドを実行する際に`docker`コマンドを実行する際に`privileged`なコンテナにしています。
詳しくは[こちら](https://qiita.com/muddydixon/items/d2982ab0846002bf3ea8)を参照して下さい。

# まとめ
`sshfs`コマンドを使うことでコンテナから他サーバのディレクトリをマウントし、ファイルをいじることができた。

# 参考
[Docker privileged オプションについて](https://qiita.com/muddydixon/items/d2982ab0846002bf3ea8)