跳至主要内容

[Docker] Command Line, CLI

keywords: tutorial, cli

TL;SC

$ docker ps [--all]       # 檢視所有 containers
$ docker exec -it <container-name> bin/bash # 連進 container 進行操作

$ docker run -it [image-id] # 根據 image 建立並執行 container
$ docker run -p 8080:8080 <image-id> # port mapping localhost port:container port
$ docker run -d redis # 讓該 container 在背景執行

# 希望能夠對某個執行中的 container 輸入一些指令
$ docker exec -it <container-id | container-name> sh

$ docker start [container-id] # 執行已經建立過的某個 container
$ docker stop [container-id] # 停止某個執行中的 container

$ docker system prune # 把所有 docker 中當前沒用到的 container 清空

# 將 container 包成 image
$ docker build -t pjchender/project_name .
$ docker build \
--file Dockerfile \
--secret id=npm_token,env=NPM_TOKEN \
--progress=plain \ # 可以顯示出 log
-t pjchender:vite-prod .

##
# docker compose
##
$ docker compose up --build # 對應到 docker build . 和 docker run <image-id>
$ docker compose up -d # 對應到類似 docker run <image-id>,-d 是在背景執行
$ docker compose down # stop and remove the containers

$ docker compose ps # 列出該 docker-compose 中有哪些 services 在執行

$ docker compose start # stop the containers
$ docker compose stop # start the containers

Docker CLI

# 根據 image 來建立並執行一個 container
# docker run <image-name>
$ docker run hello-world

# docker run <image-name> [override command] 會覆蓋掉原本在 image 內的 startup command
$ docker run -it busybox sh

# 根據 image 建立 container
$ docker create <image-name> # 會取得 container id

# 執行某個 container
# -a:監聽 container 中的 output,並顯示在 Terminal 上
$ docker start -a <container-id>

# 取得某一 Container 的 logs
$ docker logs <container-id>

# 停止某個 container
$ docker stop <container-id>

# 刪除某個 container
$ docker kill <container-id>

# 列出 containers
$ docker ps # 列出所有「正在執行」的 container
$ docker ps --all # 列出所有「被建立過」的 container

# 清除 container
$ docker system prune # 把所有 docker 中當前沒用到的 container 清空

# 對 container 執行某一指令
$ docker exec <container-id> <command>
$ docker exec -it <container-id> bash # 執行 container 的 bash shell

docker run:根據 image 來建立並執行一個 container

# 根據 image 來建立並執行一個 container
# docker run <image-name> <override-command>
$ docker run hello-world
$ docker run busybox echo hello
$ docker run busybox ls

# 執行 ubuntu 的 bash
$ docker run -it ubuntu bash

# port mapping
$ docker run -p 8080:8080 <image-id> # port localhost:container
  • docker run = docker create + docker start
  • 執行 CLI 時會透過 docker client 告知 docker server (docker daemon) 要執行的任務,接著 docker server 會在本地的 image cache 中找尋有無 hello-world 這個 image,找不到的話就會到 docker hub 上去找,找到後便把這個 image 拉到本機的 image cache 中,接著 docker server 會根據這個 image 建立 container 以執行程序。
  • 原本的 image 中都會包含 Startup Command,若想針對這個 container 執行不同的 command,可以在 docker run <image-id> [override command] 後,使用 override command
  • docker run 預設就會將 container 內的 output 顯示在 terminal 中,因此不用想 docker start 需要加上 -a 的指令才看得到

docker create & docker start

# Create a Container
$ docker create <image-name> # 會取得 container id

# Start a Container
# -a:attached to the contained 並將 output 顯示在終端機上
$ docker start -a <container-id>
  • docker create 的動作是根據 image 來建立 container,包含把 FS Snapshot 和 Startup Command 複製到 container 中
  • docker start 會去執行 container 中啟動的指令(startup command)

docker exec:在 container 中執行額外的 command

$ docker run redis  # 啟動 redis-server,container-id (11937697771a)

# $ docker exec -it <container-id> <command>
# -i 讓 STDIN 保持開啟
# -t 讓 Terminal 介面比較好看(formatted)
# -it 等於 -i -t,意思就是讓開發者可以輸入內容到 container
$ docker exec -it 11937697771a redis-cli

# 執行 container 的 bash shell,就可以進入該 container 的 shell 使用指令
# 如此就不用一直重複使用 exec 的 指令
$ docker exec -it <container-id> bash
> redis-cli # 使用 Ctrl + D 可以離開

docker logs:取得 container 輸出過的 output

$ docker create busybox echo hi there
> 35b632f6c7881

$ docker start 35b632f6c7881
$ docker logs 35b632f6c7881
  • docker logs 不會再執行一次該 container,而是把裡面曾經輸出過的 output 顯示在 terminal 中

docker stop & docker kill

$ docker create busybox ping google.com
> 81d72e56e9e

$ docker start 81d72e56e9e
$ docker stop 81d72e56e9e # send SIGTERM
$ docker kill 81d72e56e9e # send SIGKILL
  • 使用 docker stop 會向 container 發送 SIGTERM 的指令(Signal Terminate),如此程式有機會執行 graceful shutdown 的過程(例如執行 cleanup)
  • 使用 docker kill 會向 container 發送 SIGKILL 的指令,意思是要程式立即終止,不要再做任何事
  • 如果使用 docker stop 後十秒鐘 container 仍沒有被停止,則 docker 會自動執行 kill 指令

docker ps:列出所有執行中的 container

$ docker ps    # 列出所有正在執行的 container
$ docker ps --all # 列出所有被建立過的 container

docker volume

$ docker volume ls

Docker Container

docker container run --publish 80:80 --detach --name <name> nginx
docker container ls # list running containers
docker container ls -a # list all containers

docker container stop <container-ID | container-name> # stop certain container
docker container start

docker container logs <container-ID | container-name> # 顯示 container log 訊息
docker container top <container-ID | container-name> # 列出 container 內執行的程序
docker container inspect <container-ID | container-name> # 顯示 container 啟動時的設定資訊

docker container stats # 顯示 container 即時的效能狀態

docker container rm <container-ID | container-name> # 移除特定 container(須先 stop)
docker container rm -f <container-ID | container-name> # 移除特定 container(不用 stop)

docker container --help
# old way
docker container inspect # docker inspect
docker container stats # docker stats

run 和 start 的差別

透過 docker container run 總是會產生一個新的 container;透過 docker container start 則可以啟動一個停止的 container。

指令說明

docker container run

alias: docker run
啟動 container
##
# 啟動 container
# -d 在 detached mode(背景)執行 container
# -p 80:80 將本機的 80 port 對到 container 的 80 port
##

# old way: docker run
docker container run --publish 80:80 nginx

# --detach: 在背景執行,回傳 container ID
docker container run --publish 80:80 --detach nginx

# --name: 為此 container 命名
docker container run --publish 80:80 --detach --name webhost nginx

docker container run --publish 80:80 --name webhost -d nginx:1.11 nginx -T

# 啟動 mongo database
docker container run --name mongo -d mongo
docker container run -d -p 3306:3306 --name db -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
  1. Docker engine 會先在本地尋找叫做 nginx 的 image。
  2. 如果在本地的 image caches 中找不到,則從預設的 docker hub 中尋找該 image。
  3. 如果沒有指定版本,預設就是拉最新版本的 images 到 image caches 中。
  4. 一旦取得了 image 並準備就緒,將根據 image 啟動一個新的 container。
  5. Docker 將會自訂網路,並在 Docker engine 中給他一個虛擬網路內的特定虛擬 IP 位址。
  6. 指令中的 publish 是用來開放本機的 80 port 讓本機可以連結到 container 的 80 port,傳輸資料到正在執行的 container 裡面。
  • 每當啟動一個新的 container 時,便會取得一個新的獨特 ID。
  • Docker 不會製作 image 的副本,它實際上只是在 image 停止的地方上,開始了一層新的變更。
在 container 內執行指令(-it)
# 以互動形式來產生 container
# -t: pseudo-tty,模擬一個終端機,就類似 SSH 所做的一樣
# -i: interactive, keep session open to receive terminal input
# -it: 會在 container 中提供一個終端機讓你使用(Bash Shell)
docker container run -it --name <container-name> <image-name> <program>
docker container run -it --name proxy nginx bash
docker container run -it --name ubuntu ubuntu

# 重新啟動該 container
docker container start -ai

# 在現有已啟動的 container 中執行額外的程序或指令
docker container exec -it <container-name> <program>
docker container exec -it mysql bash
指定連接埠(-p)
# 打開連接埠
# -p (--publish) HOST:CONTAINER
docker container run -p <host-port>:<container:port>
docker container run -p 80:80 --name webhost -d nginx

docker container ls

# list running containers
# old way: docker ps
docker container ls
docker container ls -a

docker container inspect

# 用來檢視 container 啟動時的設定檔
docker container inspect <container-name>

# --format,使用 "GO 模板" 來格式化輸出的結果
docker container inspect webhost --format '{{ .NetworkSettings.IPAddress}}'

docker image

docker images    # 列出所有下載過的 image,等同於 docker image ls
docker image prune -a # 移除沒有用到的 docker image

資料來源