# Docker (二) - Docker 的基本操作
上一篇介紹完了[容器與 Docker 的基本概念](https://tienyulin.github.io/docker-concept/),這一篇我們要開始來介紹 Docker 的一些基本操作。
在開始操作前,我們需要先安裝 Docker,安裝的方式依照作業系統不同可以在[Docker 官網](https://docs.docker.com/engine/install/)找到相對應的安裝方式。
<!--more-->
## Docker開機自動啟動
安裝好 Docker 後,建議設定讓 Docker 開機自動啟動,才能在伺服器或電腦重啟時不用再手動啟動 Docker。
* Windows 系統設定方式:
在 Docker 的設定裡勾選 `Start Docker Desktop when you log in`
* Linux系統設定方式:
> systemctl : 負責控制 systemd 系統與服務管理器
```bash=
sudo systemctl enable docker
```
## Docker Image 的管理
安裝好 Docker 之後,就可以開始建立自己的 Image 或是下載別人做好的 Image。
### 下載 Image
我們先利用 `docker pull <ImageName>` 指令從 DockerHub 下載 [portainer](https://hub.docker.com/r/portainer/portainer) 這個 Image,portainer 是一種 Docker UI 的管理工具。
```bash=
# 從 remote repository (docker hub) 下載 image
docker pull portainer/portainer
```
### 列出 Image
下載好 portainer 後,可以透過以下兩種指令來列出所有的 Image。
```bash=
docker images
docker image ls
```
### 搜尋 Image
如果想直接搜尋 DockerHub 上面的 Image 可以透過 `search` 指令來搜尋。
```bash=
docker search ubuntu
```
### 刪除 Image
刪除 Image 可以使用 `rmi` 指令並且指定 ImageId 來刪除。
```bash=
docker rmi <ImageId>
```
若是要刪除所有的 Image,可以指定所有的 ImageId 來刪除。
* -q : 列出 Image Id
```bash=
docker rmi $(docker images -q)
```
或是 docker 本身支援的 prune 來刪除
Options :
* -a, `--all` : 刪除全部
* -f : 不跳出確認提醒
```bash=
docker image prune <options>
```
options 沒有填的話只會刪除那些沒有被引用的 Image 和 Dangling Image。
#### Dangling Image
Dangling Image 是指這個 Image 已經沒有被使用到了。例如,同樣的 Dockerfile 重新建立 Image 後,則新建立的 Image 會被 tag 為 latest,舊的 Image 不會再被用到就是 Dangling Image。
### 給 Image 加上 Tag
使用 `tag` 指令給 Image 加上 tag(標籤)。先在 Image 後面加上 `:`,接著再冒號後面填入 tag。tag 通常是版本號碼,例如: ImageName:20200611.1,20200611.1 即為標籤。
呈上,tag 可以是日期、編號或其他能代表出這個 Image 的用途。加上 tag 的目的是為了提供給這個 Image 更詳細的資訊,所以在命名上要特別注意。
另外,若是沒加上 tag,建立好的 Image 預設 tag 會是 latest,所以每次上傳到 Repository 時都是一樣的 ImageName 和 tag。而 Docker 在下載 Image 時,若沒指定 tag 就會自動代入 latest,所以為了避免混淆還是建議要加上 tag。
```bash=
docker tag <ImageName> <ImageName>:<tag>
```
### 使用 Dockerfile 建立 Image
除了下載別人做好的 Image,我們也可以自己建立 Image。至於甚麼是 Dockerfile ? 又該如何建立成 Image 呢 ?
詳細作法請參考下一篇 [Docker(三) - 撰寫 Dockerfile](https://tienyulin.github.io/docker-dockerfile/)
## Docker Container 的管理
有了 Image 之後我們就可以使用 Image 來建立 Container。
### 建立 Container
使用 `docker run <ImageName>` 就可以建立起一個 Container,但是通常還會再給予一些變數來設定要啟動的 Container,例如:
* -d : 背景執行
* -h : 自訂 Host Name
* -i : 進入互動模式(interaactive),讓 Container 的標準輸入保持打開
* -t : 配置一個虛擬終端(pseudo-tty)並綁定到 Container 上
* -p : 設定要對外開啟的 port number(host port:container port)
* -e : 設定環境變數
* -v : 資料對應(host folder:container folder)
* `--name` : 自訂 Container 名稱
* `--restart` : 設定重啟模式,預設是 No,但實務上應設定 always 才不會因為意外停止還需要人為手動重啟
以下以建立 portainer 的 Container 為例,如果 Image 已經有下載過了,則建立 Container 時會直接拿來做使用,若是沒有下載 Image,在建立時 Docker 會自動去 DockerHub 上面下載下來再使用。
```bash=
docker run \
-d \
--restart always \
--name portainer \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /volume1/docker/portainer:/data \
portainer/portainer
```
建立好後,直接打開瀏覽器輸入 `http://127.0.0.1:9000/` 就會進入到登入畫面,即表示建立成功。
### 列出 Cotainer
透過 `docker ps -a` 可以列出所有的 Container。
```bash=
docker ps -a
```
如果只想列出正在執行的 Container,則使用 `docker ps` 即可。
```bash=
docker ps
```
### 啟動 Container
若是有建立好的 Container 沒有啟動或是因為某些緣故停止了需要手動啟動,可以使用 `start` 指令來啟動。
```bash=
docker start <ContainerName>
```
### 停止 Container
```bash=
docker stop <ContainerName>
```
### 刪除 Container
```bash=
docker rm <ContainerId>
```
### 查看 Container log
使用 `docker logs` 可以查看 Container 的執行紀錄。
* -f : 持續印出執行紀錄不會跳離,可以不加
```bash=
docker logs -f <ContainerName>
```
### 進入 Container
如果需要對 Container 進行操作,而且必需進到 Container 內,可以使用 `exec` 指令來對 Container 執行`bash`。
* -i: 進入互動模式(interaactive),讓 Container 的標準輸入保持打開
* -t: 配置一個虛擬終端(pseudo-tty)並綁定到 Container 上
```bash=
docker exec -it <containerName> bash
docker exec -it <containerName> /bin/bash
# 有些 Image 使用 Alpine Linux,可能沒有 bash,改用 sh
docker exec -it <containerName> /bin/sh
```
exec 後面接到 bash 或是 /bin/bash 其實都是 Container 裡的指令,只是打開 Container 的 bash,所以如果沒有一定要開 bash,其實也可以直接輸入指令。例如 :
```bash=
docker exec -it <containerName> ls
```
進入 Container 的另一種方式是使用 `attach` 指令,但是退出 Container 時會導致 Container 停止,所以實務上不太會使用。
```bash=
docker attach <containerName>
```
### 清除沒有執行的 Container、Image 、Network 和 Cache
Options :
* `--all` , -a : 刪除所有停止的 Container、Image、Network
* `--force`, -f : 強制刪除不跳出確認提醒
* `--volumes` : 刪除 Volume
* `--filter` : 刪除指定 label 的 Container、Image、Network、Volume
```bash=
docker system prune <options>
```
options 沒有填的話只會刪除那些沒有被引用的 Image 和 [Dangling Image](#Dangling-Image)。
## Docker 推送 Image 到 Repository
除了 DockerHub 有提供 Container Registry 讓開發者存放 Image,Google、Microsoft 等等的公司也都有提供,以下以 DockerHub 的 Repository 為範例進行操作。
### 新建 Repository
首先要在 DockerHub 註冊帳號,新建一個 Repository,每個帳號有一個免費的 Private Repository,其他的 Repository 必須是 Public。
接下來回到 CommandLine 開始準備要上傳的 Image。
### 給 Image 加上 Tag
因為要上傳到 DockerHub 所以還必須指定 DockerHubUserName 和 RepositoryName,這樣再上傳的時候才會傳到對應的 Repository。
```bash=
docker tag <ImageName> <DockerHubUserName>/<RepositoryName>/<ImageName>:<Tag>
```
### 登入 DockerHub
準備好 Image 後,接著就可以開始上傳了。上傳前要先使用 `login` 指令登入 Docker 的帳戶,再輸入 UserName 和 Password。
```bash=
docker login
```
也可以加上 `-u` 和 `-p` 或是 `--username` 和 `--password`,直接打上帳號密碼,一次完成登入步驟
```bash=
docker login -u <UserName> -p <Password>
docker login --username <UserName> --password <Password>
```
### 上傳 Image
上傳使用的是 `push` 指令,將已經加好 tag 的 Image 上傳到 Repository。
```bash=
docker push <DockerHubUserName>/<RepositoryName>/<ImageName>:<Tag>
```
### 登出 DockerHub
上傳完記得要登出 DockerHub。
```bash=
docker logout
```
## Summary
以上介紹完了常用的 Docker 操作方法和指令,下一篇將介紹如何使用 Dockerfile 自己建立 Image。
## 參考
[1] [Docker(一) - 容器與 Docker 的基本概念](/Cz7PXrF0SEeT0LLDsLYeLw)
[2] [把 Docker Image Push 到 Docker Hub](https://ithelp.ithome.com.tw/articles/10191139)
[3] [Docker 基本教學](https://ithelp.ithome.com.tw/articles/10199339)
[4] [Docker 學習筆記(三) — Docker指令講解](https://medium.com/%E4%B8%80%E5%80%8B%E5%B0%8F%E5%B0%8F%E5%B7%A5%E7%A8%8B%E5%B8%AB%E7%9A%84%E9%9A%A8%E6%89%8B%E7%AD%86%E8%A8%98/docker-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-docker%E6%8C%87%E4%BB%A4%E4%BD%BF%E7%94%A8%E8%AC%9B%E8%A7%A3-9040d9de4677)
[5] [docker system prune](https://docs.docker.com/engine/reference/commandline/system_prune/#examples)
[6] [如何快速清理 Docker 無用資源](https://kknews.cc/zh-tw/code/kbb6byq.html)
###### tags: `Container` `Docker`