0%

docker 系列 - (1) 容器快速上手

1. docker命令行的基本使用

docker + 管理的對象(比如容器、鏡像) + 具體操作(比如創建、啟動、停止、刪除)

  • docker image pull nginx 拉取一个叫nginx的docker image鏡像
  • docker container stop web 停止一个叫web的docker container容器

2. Image vs Container 鏡像 vs 容器

2.1. image鏡像

  • docker image 是一個 read-only文件
  • 這個文件包含文件系統、源碼、庫文件、依賴、工具等一些運行application所需要的文件
  • 可以理解成一個模板
  • docker image具有分層的概念

2.2. container容器

  • “一個運行中的docker image”

  • 實質是複製image全在image最上層加上一層read-write的層(稱之為`container layer,容器層)

  • 基於同一個image可以創建多個container

    docker-image-vs-container

3. docker image的獲取方式

  • 自己製作
  • 從registry拉取(比如docker hub)

4. 容器的基本操作

1
2
#docker 版本
dcoker version
1
2
#docker 相關資訊,比如目前有幾個container、images、container運行狀態
docker info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#可以以看到列出了managment commands 、commands 
docker

Management Commands:
builder Manage builds
buildx* Docker Buildx (Docker Inc., v0.7.1)
compose* Docker Compose (Docker Inc., v2.2.1)
config Manage Docker configs
container Manage containers
context Manage contexts
image Manage images
manifest Manage Docker image manifests and manifest lists
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
scan* Docker Scan (Docker Inc., 0.9.0)
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes

Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes

1
2
3
4
5
6
7
8
9
10
11
#針對container 指令查看
docker container --help
#針對image 指令查看
docker image --help

#列出image
docker image ls

#刪除image
docker image rm docker/getting-started

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#創建container
docker container run

#創建container nginx ,本地沒有找到直接去找docker hub 下載 並直接運行,並且是前台運行的container
docker container run nginx

#列出container ,ps 為較舊版本的命令 ,ls、ps效果是一樣的
docker container ls
docker container ps

#列出container 包含stop的container

docker container ps -a
docker container ls -a
docker ps -a

#docker run 省略container 是較舊的寫法
docker container run nginx
docker run nginx

#停止容器
docker container stop [NAMES] or [Container id]
docker stop [NAMES] or [Container id]

#刪除容器
docker container rm [NAMES] or [Container id]
docker rm [NAMES] or [Container id]

4.1. Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker container run nginx
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
343fd4031609 nginx "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 80/tcp xenodochial_clarke
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
343fd4031609 nginx "/docker-entrypoint.…" 14 seconds ago Up 13 seconds 80/tcp xenodochial_clarke
$ docker container stop 34
34
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
343fd4031609 nginx "/docker-entrypoint.…" 29 seconds ago Exited (0) 5 seconds ago xenodochial_clarke
d9095daa8bcf nginx "/docker-entrypoint.…" 28 minutes ago Exited (0) 28 minutes ago suspicious_shamir
$ docker container rm 34
34
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d9095daa8bcf nginx "/docker-entrypoint.…" 28 minutes ago Exited (0) 28 minutes ago suspicious_shamir
$

5. 命令行小技巧之批次操作

5.1. 批次停止

先查詢目前的清單如下

1
2
3
4
5
6
7
$ docker container ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd3a825fedeb nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 80/tcp mystifying_leakey
269494fe89fa nginx "/docker-entrypoint.…" 9 seconds ago Up 8 seconds 80/tcp funny_gauss
34b68af9deef nginx "/docker-entrypoint.…" 12 seconds ago Up 10 seconds 80/tcp interesting_mahavira
7513949674fc nginx "/docker-entrypoint.…" 13 seconds ago Up 12 seconds 80/tcp kind_nobel

方法1

1
2
#刪除多個container ,以下為例刪除4個container
docker container stop af 87 c2 4c

方法2

透過以下指令我們可以發現會出輸id清單

1
2
3
4
5
6
7
#輸出 conainter id list
docker container ps -aq

cd3a825fedeb
269494fe89fa
34b68af9deef
7513949674fc

接著利用以下方式批次停用container

1
docker container stop $(docker container ps -qa)

5.2. 批次刪除

1
2
3
4
5
#批次刪除
docker container rm $(docker ps -aq)

#批次強制刪除
docker container rm -f $(docker container ls -aq)

補充說明:

  • container 在運行的過程中是不行刪除的,除非先stop。

另一個方法是強制刪除,如下:

1
docker container rm 704 -f
  • 可以快速對系統進行清理,删除停止的容器,不用的image,等等
1
docker system prune -a -f

6. 容器的attached和detached模式

6.1. attached

前台的執行我們稱之為attached ,輸入輸出的結果attached本地的輸入輸出,也會將ctrl + c 輸入(反應)至容器內部。

而windows 的attached 不是完整的attached,只有做到容器的輸出打印出來,無法接收ctrl + c 的輸入指令。(LINUX 是完整attach)

1
2
#前台模式執行docker
docker container run -p 80:80 nginx

指令說明:-p 80:80 對外port:容器port ,也就是對外的80 port 映射容器 80 port

6.2. detached

後台的執行我們稱之為detached

1
2
3
#背景模式執行docker 以下二種都可以
docker run --detach -p
docker run -d -p

我們發現這樣執行後,只有拿到container id的輸出,我們看不到nginx 的log 輸出囉

如果想要去attach這個容器,使用以下指令:

1
docker attach [NAMES] or [Container id]

我們會發現再去打開瀏覽器刷新一下頁面(http://localhost:80),回過頭來看terminal就會看到nginx有輸出log 囉。

image-20220214133614727

小結:我們比較常用的是detached 創建容器。

7. 容器的交互式模式

7.1. docker container logs 介紹

除了我們稍早講到的 docker attch指令方法得到相關log,也可以使用另外一個指令:

1
docker container logs [NAMES] or [Container id]

這個指令是取得/docker-entrypoint.sh腳本輸出。

image-20220214140333028

如果我們需要即時出輸log的話可以透過以下指令:

1
docker container logs -f [NAMES] or [Container id]

image-20220214140509765

接著,再去打開瀏覽器刷新一下頁面(http://localhost:80),回過頭來看terminal就會看即時的log輸出囉

image-20220214140439035

image-20220214140415333

7.2. 創建容器時並進入交互式模式

透過以下指令可以進行交互模式:

1
docker container run -it ubuntu sh

image-20220214140232538

進入到了container 內部,當要離開container 時只要輸入exit指令就行了。

我們再去觀查docker container ps -a 會發現剛剛的ubuntu container 是停止的

image-20220214140127592

7.3. 在一個已經運行的容器裡執行一個額外的command

查看一下目前容器的狀態與ID

1
docker ps

image-20220214152023529

執行以下指令進入到容器內部

1
2
3
4
docker exec -it [NAMES] or [Container id] sh

#例子
docker exec -it ae4 sh

image-20220214152108100

7.4. BusyBox 介紹

BusyBox是一個集成了一百多個最常用linux命令和工具(如catechogrepmount‘、telnet等)的精簡工具箱,它只需要幾MB的大小,很方便進行個種快速驗證,被譽為”LINUX系統的瑞士軍刀”。

BusyBox可運行於多款POSIX環境的操作系統中,如LINUX(包括android)、HurdFreeBSD等。

BusyBox 鏡像雖然小巧,但包括了大量常見的 Linux 命令,讀者可以用它快速熟悉 Linux 命令。

8. 容器和虛擬機 Container vs VM

docker-vs-vm

8.1. 虛擬機

  • 要虛擬出完整的系統包含了作業系統
    • 需要Hypervisor支持,並且在這些軟件之上創建虛擬機
      • vmware
      • virtual box

8.2. 容器

  • 運行在container engine之上的虛擬容器

8.3. 容器不是Mini虛擬機

  • 容器其實是進程
    • Container are just processes
  • 容器中的進程被限制了對CPU、記憶體等資源的訪問
    • 我們可以對容器進行一些限制,比方說CPU使用2核、記憶體只能使用1G。這概念在VM也是可以的。
  • 當進程停止後,容器就退出了。

8.4. 證明容器即是process

首先使用 docker ps 找目前容器的id

image-20220215152923918

我們會看到其實nginx 是執行一個 docker-entrypoint.sh 的一個腳本,這個腳本當然也就是自動啟用nginx的相關指令。

我們輸入 docker container top [Names] or [Container id] ,會顯示出這個容器裡面運行了哪些進程,下圖我們試著輸入docker container top 6cb

image-20220215153056159

我們可以看到在CMD有一個主進程(master process) ,而PPID欄位指的是此進程的父進程是誰,比方說4576、4577 的父進程都是指向4516 ,而我們再去找PID為4516的,我們會發現也就是我們剛剛講是主進程的那筆。

接著,我們使用ps aux |grep nginx (我們的環境為ubuntu),如下:

image-20220215160459890

在ubuntu 的進程裡,我們會發現 4516 這個id 也就是剛剛在container 裡面找到的master process,也就證明了,container 的確是一個進程。

8.4.1. 透過pstree工具來查看進程的依賴關係

接著,我們使用pstree -halps 4576,如下:

image-20220215160841953

我們可以看到進程的依賴關係。其中containerd-shim就是一個創建並啟動nginx的那個進程,後面的id也就是啟動之後的id名稱

8.5. container 內部進程跟host進程是對不上的,是怎麼回事?

1
在container 內的進程id 跟host 的進程id 剛好對上,但其實具體上container 並不是這個id,這個涉及到容器的命名空間原理、隔離等等觀念技術。後續會再講到。

簡單的示例

我們啟動一個有多指令的容器busybox,並利用docker container top dd4查看進程資料。

image-20220215162233126

另外下面這張圖是進入到容器內之後,下了ps指令,我們會發現跟上一張圖片對比的PID 是不一樣的。

image-20220215162430641

9. docker container run 背後發生了什麼?

1
2
3
4
5
docker container run -d --publish 80:80 --name webhost nginx
# -d 後台運行
# --publish 也就是先前的 -p 80:80
# --name 給這個容器取名
# nginx 後面可以再接執行的腳本名稱,如果沒有下,就會執行預設的腳本,後續會講到。
  • 在本地查找是否有nginx這個image鏡像,但是沒有發現
  • 去遠程的image registry查找nginx鏡像(預設的registry是docker hub)
  • 下載最新版本的nginx鏡像(nginx:latest 預設)
  • 基於nginx鏡像來創建一個新的容器,並且準備運行
  • docker enginer 分配給這個容器一個虛擬ip地址
  • 在宿主機上打開80port 並把容器的80port轉發到宿主(host)機上
  • 啟動容器,運行指定的命令(這裡是一個shell腳本去啟動nginx)