###### tags: `tutorials` `docker` `ubuntu` `linux` `cuda` `GPU` `NVIDIA` `python` `deep learning` `AI`
# Docker 使用教學
#### 更多資訊請參考 https://docs.docker.com/reference/
## 檢視
- 檢視所有 image
~~~bash= !
$ docker images
~~~
- 檢視所有 container
~~~bash= !
$ docker container ls -a
~~~
或
~~~bash= !
$ docker ps -a
~~~
- 檢視所有正在執行的 container
~~~bash= !
$ docker container ls
~~~
或
~~~bash= !
$ docker ps
~~~
## 停止與刪除
### Container
- 停止 container
~~~bash= !
$ docker stop {containerID(s)}
~~~
- 強制停止 container
~~~bash= !
$ docker kill {containerID(s)}
~~~
- 刪除 container (PS: container 要是處於`停止`狀態)
~~~bash= !
$ docker rm {containerID(s)}
~~~
- 刪除所有已停止的 container
~~~bash= !
$ docker container prune
~~~
- 停止全部 container (**Not recommended**)
~~~bash= !
$ docker stop $(docker ps -aq)
~~~
- 刪除全部 container (**Not recommended**)
~~~bash= !
$ docker rm $(docker ps -aq)
~~~
- 強制刪除全部 container (**Not recommended**)
~~~bash= !
$ docker rm -f $(docker ps -aq)
~~~
:::info
`docker ps -q` 是只列出 container ID
{containerID(s)} 不用全打,只要打到不會和其他 ID 重複的部分就可以抓的到了
:::
---
### Image
- 刪除 image (PS: 要完全沒有任何 container 使用該 image)
~~~bash= !
$ docker rmi {imageID(s)}
~~~
- 刪除所有沒在用的 image
~~~bash= !
$ docker image prune -a
~~~
- 刪除沒有 tag 的 image (**Not recommended**)
~~~bash= !
$ docker rmi $(docker images -f "dangling=true" -q)
~~~
- 刪除全部 image (**Not recommended**)
~~~bash= !
$ docker rmi $(docker images -q)
~~~
:::info
`docker images -q` 是只列出 image ID
在 `rmi` 後加入 `-f` 是強制刪除,一樣也是不建議使用
{image_ID(s)} 不用全打,只要打到不會和其他 ID 重複的部分就可以抓的到了
:::
## 建立與執行
### Create image
~~~bash= !
$ docker build -t {image_repository}:{image_tag} {daemon_path} -f {path_to_dockfile} --build-arg {ARG_param_name}={ARG_value}
~~~
- `-t`: 也可以寫成 `--tag`,給創立的 image tag name
- {image_repository}: image repository
- {image_tag}: image tag
- {daemon_path}: 如果 `Dockerfile` 有些檔案是從外部找會從該路徑下找 (一般很少用,所以通常都是用 `.`)
- `-f`: 也可以寫成 `--file`,用來指定要用哪個路徑下的 `Dockerfile` 來建立 image,`Dockerfile` 名字可以取其他名字
- {path_to_dockfile}: `Dockerfile` 的路徑
- `--build-arg`: 由外部給予內部 `ARG` 值,如果要給多個值,每個都要給前綴 `--build-arg`,不能只寫一次給多個 `ARG`
:::info
如果在只有 `Dockerfile` 的路徑下,且 `Dockerfile` 的名字也是叫 `Dockerfile`,可以不用加上 `-f`
:::
> 有關 `Dockerfile` 的相關寫法可以看 [Dockerfile 建立教學](/@jimmy801/docker_file)
---
### Run container
:::spoiler **舊版(docker-ce < 19.03)**
#### 使用 nvidia-docker run container
~~~bash= !
$ nvidia-docker run -it -h {container_hostname} --name {container_name} -v {local_path_to_volume}:{container_path} --shm-size {shm_size} -d {imageID_or_repo:Tag}
~~~
- `-it`: 代表在執行 Docker 虛擬容器環境時,開啟虛擬終端機,以互動的模式執行
- `-h`: 指定 container hostname
- `--name`: 指定該 container 名字
- {container_name}: 指定的 container 名字
- `--shm-size`: 指定該 container 可以使用的 shared memerory
- {shm_size}: 指定的 shared memerory 大小,如 `1G`, `4G`
:::danger
如果 shared memerory 不足會出現 `ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm).`
:::
- `-d`: 背景執行 container
- {imageID_or_repo:Tag}: 用指定 image 來跑 container,可以用 image 的 id 或是 {image_repository}:{image_tag}
- `-v`: 執行 container 時,把目前的某個位置掛載到 container 中
- {local_path_to_volume}: 要掛載進 container 的外部 local **絕對路徑**
- {container_path}: 掛載進 container 內的指定路徑 (預設路徑是在 `/` 下,可以使用相對於 `/` 的相對路徑,或是絕對路徑,若是資料夾不存在則會自動建立資料夾)
:::warning
掛載多個資料夾則要多加幾個 -v
像是 `-v /on/my/host/1:/on/the/container/1 -v /on/my/host/2:/on/the/container/2`
:::
> 更多資訊請看[這裡](https://docs.docker.com/engine/reference/commandline/run/)
:::
#### 新版 (docker-ce >= 19.03)
~~~bash= !
$ docker run -it --gpus {gpu_cond} -h {container_hostname} --name {container_name} -v {local_path_to_volume}:{container_path} --shm-size {shm_size} -d {imageID_or_repo:Tag}
~~~
- `-it`: 代表在執行 Docker 虛擬容器環境時,開啟虛擬終端機,以互動的模式執行
- `--gpus`: 指定要使用的 GPU
- {gpu_cond}: 常用的是 `device=0,2` 代表只用指定的 `0` 和 `2` 號 GPU,或是使用 `all` 代表使用全部 GPU
:::info
使用時是 `--gpus device=0,2` (等價於 `--gpus 0,2`)來指定只使用 `0` 和 `2` 號 GPU,或是使用 `--gpus all` 使用全部 GPU
:::
- `-h`: 指定 container hostname,一般是會顯示於 *bash* 中的 `{user_name}@{host_name}:{path}#` 的 `{host_name}` 中
- `--name`: 指定該 container 名字
- {container_name}: 指定的 container 名字
- `--shm-size`: 指定該 container 可以使用的 shared memerory
- {shm_size}: 指定的 shared memerory 大小,如 `1G`, `4G`
:::danger
如果 shared memerory 不足會出現 `ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm).`
:::
- `-d`: 背景執行 container
- {imageID_or_repo:Tag}: 用指定 image 來跑 container,可以用 image 的 id 或是 {image_repository}:{image_tag}
- `-v`: 執行 container 時,把目前的某個位置掛載到 container 中
- {local_path_to_volume}: 要掛載進 container 的外部 local **絕對路徑**
- {container_path}: 掛載進 container 內的指定路徑 (預設路徑是在 `/` 下,可以使用相對於 `/` 的相對路徑,或是絕對路徑,若是資料夾不存在則會自動建立資料夾)
:::warning
掛載多個資料夾則要多加幾個 -v
像是 `-v /on/my/host/1:/on/the/container/1 -v /on/my/host/2:/on/the/container/2`
:::
> 更多資訊請看[這裡](https://docs.docker.com/engine/reference/commandline/run/)
---
### Execute container
~~~bash= !
$ docker exec -it {containerID_or_name} {run_cmd}
~~~
- `-it`: 代表在執行 Docker 虛擬容器環境時,開啟虛擬終端機,以互動的模式執行
- {containerID_or_name}: 指定執行的 container ID 或名字
- {run_cmd}: 執行 container 時自動執行的 command,一般不需要設就寫 `bash` 就好
> 更多資訊請看[這裡](https://docs.docker.com/engine/reference/commandline/exec/)
---
### More command
- 將 conatiner 外的檔案(或資料夾)複製進 container 內
~~~bash= !
$ docker cp {local_path} {containerID_or_name}:{container_path}
~~~
- {local_path}: 要複製進 container 的外部 local 檔案路徑
- {containerID_or_name}: 要複製進的 container ID 或名字
- {container_path}: 複製檔案到的 container 內的指定路徑
- 重新命名 container
~~~bash= !
$ docker rename {containerID_or_name} {new_container_name}
~~~
- {containerID_or_name}: 要重新命名的 container ID 或名字
- {new_container_name}: container 的指定名字
- 重新啟動 container
~~~bash= !
$ docker restart {containerID_or_name}
~~~
- {containerID_or_name}: 要重啟的 container ID 或名字
- 用現有的 container 建立 image
~~~bash= !
$ docker commit {containerID_or_name} {image_repository}:{image_tag}
~~~
- {containerID_or_name}: 現有的 container ID 或名字
- {image_repository}: image repository
- {image_tag}: image tag
- 將 image 存成檔案
~~~bash= !
docker save -o {path_for_generated_tar_file} {image_repository}:{image_tag}
~~~
- {path_for_generated_tar_file}: 存放檔案的 path
- {image_repository}: image repository
- {image_tag}: image tag
- 將 image 檔案讀取成 image
~~~bash=
docker load -i {path_to_image_tar_file}
~~~
- {path_to_image_tar_file}: image 檔案的 path
# More Usage
{%hackmd @jimmy801/SSH_docker %}
---
{%hackmd @jimmy801/docker_tb_jp %}
---
{%hackmd @jimmy801/docker_gui %}
---
{%hackmd @jimmy801/docker_issue %}