Linux学習用に、データ永続化したDockerコンテナを用意する

# 実現したいこと

- Linux環境(Debian)であること
- コンテナを削除してもデータが消えず、再作成した際にそのままデータが残っていること<br>
(ただしホームディレクトリ以下のみを対象とする)

# ディレクトリ構成

`Dockerfile` と `data` ディレクトリをホストマシンに用意しておきます。

```zsh

$ tree .
.
├── Dockerfile
└── data

1 directory, 1 file
```

# Dockerfile

`Dockerfile` の内容は以下の通りです。

`ARG UID=501` の「501」は、ホストマシンで `id` コマンドを打って確認した値ですので、ご自身で試される場合は適宜書き換える必要があります。

`y_tsubasa` の部分は任意のユーザ名を使用します。今回は、ホストマシンのユーザ名と合わせました。

`useradd` コマンドで一般ユーザを追加しますが、`-m` オプションを付与することで、ホームディレクトリも合わせて作成します。

```:Dockerfile
FROM debian

ARG UID=501
RUN useradd -m -u ${UID} y_tsubasa
USER ${UID}
```

# コマンド

以下のコマンドを使用します。

## イメージ構築

```
$ docker build -t linux-training .
```

## コンテナ作成&起動

`-v` オプションで、ホストマシンのディレクトリをマウントしています。
つまり、ホストマシンの `data` ディレクトリとコンテナ内のホームディレクトリ `/home/y_tsubasa` でデータを共有するようになります。

`-w` オプションで、ログイン時のカレントディレクトリを指定しています。
(付与しない場合は、ルートディレクトリとなります)

```
$ docker run -v ~/repo-private/linux-training/data:/home/y_tsubasa \
             -w /home/y_tsubasa \
             --name linux-training \
             -it linux-training
```

## コンテナ再起動

```
$ docker start -ai linux-training
```

# 実際に動かしてみる

コンテナを作成&起動します。

```
$ docker run -v ~/repo-private/linux-training/data:/home/y_tsubasa \
             -w /home/y_tsubasa \
             --name linux-training \
             -it linux-training
y_tsubasa@c04b4bbfb4c9:~$ 
```

ファイルを作成し、`exit` します。

```
y_tsubasa@c04b4bbfb4c9:~$ ls
y_tsubasa@c04b4bbfb4c9:~$ touch test
y_tsubasa@c04b4bbfb4c9:~$ ls
test
y_tsubasa@c04b4bbfb4c9:~$ exit
```

(一応)再起動して、ファイルが残っていることを確認します。

```
$ docker start -ai linux-training
y_tsubasa@c04b4bbfb4c9:~$ ls
test
y_tsubasa@c04b4bbfb4c9:~$ exit
```

コンテナを削除します。

```
$ docker ps -a | grep linux
c04b4bbfb4c9        linux-training                "bash"                   About a minute ago   Exited (0) 14 seconds ago                       linux-training
$ docker rm c04b4bbfb4c9
c04b4bbfb4c9
```

コンテナを新しく作成&起動し、ファイルがあることを確認します。

```
$ docker run -v ~/repo-private/linux-training/data:/home/y_tsubasa \
             -w /home/y_tsubasa \
             --name linux-training \
             -it linux-training
y_tsubasa@e58a1f1bfcca:~$ ls
test
```

ホストマシンからも、ファイルを確認できます。

```
$ ls data
test
```

# (2020-08-25追記) sudoできるようにする

試しに、vim をインストールするところまでやってみます。

## Dockerfileを修正

rootユーザーと一般ユーザーにパスワードの設定をしています。
また、sudoをインストールするようにし、一般ユーザーを `/etc/sudoers` に追加しています。

```:Dockerfile
FROM debian

RUN echo 'root:root' | chpasswd

ARG UID=501
RUN useradd -m -u ${UID} y_tsubasa
RUN echo 'y_tsubasa:password' | chpasswd

RUN apt update
RUN apt -y install sudo

RUN echo "y_tsubasa    ALL=(ALL)       ALL" >> /etc/sudoers

USER ${UID}
```

## イメージ再構築

コマンドは変わりません。

```
$ docker build -t linux-training .
```

## コンテナ作成&起動

コマンドは変わりません。

```
$ docker run -v ~/repo-private/linux-training/data:/home/y_tsubasa \
             -w /home/y_tsubasa \
             --name linux-training \
             -it linux-training
```

## 実際にsudoしてみる

sudoできるようになっているはずなので、vimをインストールしてみます。

```
y_tsubasa@5ecbd666457b:~$ sudo apt -y install vim

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for y_tsubasa: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libgpm2 vim-common vim-runtime xxd
Suggested packages:
  gpm ctags vim-doc vim-scripts
The following NEW packages will be installed:
  libgpm2 vim vim-common vim-runtime xxd
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 7425 kB of archives.
After this operation, 33.8 MB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 xxd amd64 2:8.1.0875-5 [140 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 vim-common all 2:8.1.0875-5 [195 kB]
Get:3 http://deb.debian.org/debian buster/main amd64 libgpm2 amd64 1.20.7-5 [35.1 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 vim-runtime all 2:8.1.0875-5 [5775 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 vim amd64 2:8.1.0875-5 [1280 kB]
Fetched 7425 kB in 1s (6757 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package xxd.
(Reading database ... 6807 files and directories currently installed.)
Preparing to unpack .../xxd_2%3a8.1.0875-5_amd64.deb ...
Unpacking xxd (2:8.1.0875-5) ...
Selecting previously unselected package vim-common.
Preparing to unpack .../vim-common_2%3a8.1.0875-5_all.deb ...
Unpacking vim-common (2:8.1.0875-5) ...
Selecting previously unselected package libgpm2:amd64.
Preparing to unpack .../libgpm2_1.20.7-5_amd64.deb ...
Unpacking libgpm2:amd64 (1.20.7-5) ...
Selecting previously unselected package vim-runtime.
Preparing to unpack .../vim-runtime_2%3a8.1.0875-5_all.deb ...
Adding 'diversion of /usr/share/vim/vim81/doc/help.txt to /usr/share/vim/vim81/doc/help.txt.vim-tiny by vim-runtime'
Adding 'diversion of /usr/share/vim/vim81/doc/tags to /usr/share/vim/vim81/doc/tags.vim-tiny by vim-runtime'
Unpacking vim-runtime (2:8.1.0875-5) ...
Selecting previously unselected package vim.
Preparing to unpack .../vim_2%3a8.1.0875-5_amd64.deb ...
Unpacking vim (2:8.1.0875-5) ...
Setting up libgpm2:amd64 (1.20.7-5) ...
Setting up xxd (2:8.1.0875-5) ...
Setting up vim-common (2:8.1.0875-5) ...
Setting up vim-runtime (2:8.1.0875-5) ...
Setting up vim (2:8.1.0875-5) ...
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rvim (rvim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rview (rview) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vi (vi) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/view (view) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/ex (ex) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in auto mode
Processing triggers for libc-bin (2.28-10) ...
```

無事インストールできました！

```
y_tsubasa@5ecbd666457b:~$ vim --version                                  
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15)
Included patches: 1-875, 878, 884, 948, 1046, 1365-1368, 1382, 1401
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version without GUI.  Features included (+) or not (-):
+acl               +extra_search      +mouse_netterm     +tag_old_static
+arabic            +farsi             +mouse_sgr         -tag_any_white
+autocmd           +file_in_path      -mouse_sysmouse    -tcl
+autochdir         +find_in_path      +mouse_urxvt       +termguicolors
-autoservername    +float             +mouse_xterm       +terminal
-balloon_eval      +folding           +multi_byte        +terminfo
+balloon_eval_term -footer            +multi_lang        +termresponse
-browse            +fork()            -mzscheme          +textobjects
++builtin_terms    +gettext           +netbeans_intg     +textprop
+byte_offset       -hangul_input      +num64             +timers
+channel           +iconv             +packages          +title
+cindent           +insert_expand     +path_extra        -toolbar
-clientserver      +job               -perl              +user_commands
-clipboard         +jumplist          +persistent_undo   +vartabs
+cmdline_compl     +keymap            +postscript        +vertsplit
+cmdline_hist      +lambda            +printer           +virtualedit
+cmdline_info      +langmap           +profile           +visual
+comments          +libcall           -python            +visualextra
+conceal           +linebreak         -python3           +viminfo
+cryptv            +lispindent        +quickfix          +vreplace
+cscope            +listcmds          +reltime           +wildignore
+cursorbind        +localmap          +rightleft         +wildmenu
+cursorshape       -lua               -ruby              +windows
+dialog_con        +menu              +scrollbind        +writebackup
+diff              +mksession         +signs             -X11
+digraphs          +modify_fname      +smartindent       -xfontset
-dnd               +mouse             +startuptime       -xim
-ebcdic            -mouseshape        +statusline        -xpm
+emacs_tags        +mouse_dec         -sun_workshop      -xsmp
+eval              +mouse_gpm         +syntax            -xterm_clipboard
+ex_extra          -mouse_jsbterm     +tag_binary        -xterm_save
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H   -Wdate-time  -g -O2 -fdebug-prefix-map=/build/vim-4Pursk/vim-8.1.0875=. -fstack-protector-strong -Wformat -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim        -lm -ltinfo -lnsl  -lselinux -lacl -lattr -lgpm -ldl
```

# 参考

- [Docker コンテナ内に一般ユーザーを作成する](https://zukucode.com/2019/06/docker-user.html)
- [useraddコマンドについて詳しくまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-useradd#-g--gid_GROUPGID)
- [Dockerfile リファレンス — Docker\-docs\-ja 17\.06 ドキュメント](https://docs.docker.jp/engine/reference/builder.html#user)
- [build — Docker\-docs\-ja 17\.06 ドキュメント](https://docs.docker.jp/engine/reference/commandline/build.html)
- [run — Docker\-docs\-ja 17\.06 ドキュメント](http://docs.docker.jp/engine/reference/commandline/run.html)
- [start — Docker\-docs\-ja 17\.06 ドキュメント](https://docs.docker.jp/engine/reference/commandline/start.html)
- [コンテナでデータを管理 — Docker\-docs\-ja 17\.06 ドキュメント](https://docs.docker.jp/engine/tutorials/dockervolumes.html#mount-a-host-directory-as-a-data-volume)
- [sudoできるユーザの追加をDockerfileに書いてみた \- Qiita](https://qiita.com/0ashina0/items/1bd4b54f0e49a643e8a2)