Docker 使用 Google 公司推出的 Go 語言 進行開發實現,基於 Linux 內核的 cgroup,namespace,以及 OverlayFS 類的 Union FS 等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術。由於隔離的進程獨立於宿主和其它的隔離的進程,因此也稱其為容器... ...
Docker基礎和常用命令
一,Docker 簡介
1.1,什麼是 Docker
Docker
使用 Google 公司推出的 Go 語言 進行開發實現,基於 Linux 內核的 cgroup,namespace,以及 OverlayFS 類的 Union FS 等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術。由於隔離的進程獨立於宿主和其它的隔離的進程,因此也稱其為容器。Docker容器與虛擬機類似,但二者在原理上不同。容器是將操作系統層虛擬化,虛擬機則是虛擬化硬體,因此容器更具有便攜性、能更高效地利用伺服器。
專業名詞 Docker
有兩個意思:
- 代指整個 Docker 項目。
- 代指 Docker 引擎。
Docker 引擎(Docker Engine)是指一個服務端-客戶端結構的應用,主要有這些部分:Docker 守護進程、Docker Engine API(頁面存檔備份,存於互聯網檔案館)、Docker 客戶端。
1.2,Docker 與虛擬機的區別
- 傳統虛擬機技術是虛擬出一套硬體後,在其上運行一個完整操作系統,在該系統上再運行所需應用進程。
- Docker 容器內的應用進程直接運行於宿主的內核,容器內沒有自己的內核,而且也沒有進行硬體虛擬。因此容器要比傳統虛擬機更為輕便。
特性 | Docker | 虛擬機 |
---|---|---|
啟動 | 秒級 | 分鐘級 |
硬碟使用 | 一般為 MB | 一般為 GB |
性能 | 接近原生 | 弱於 |
系統支持量 | 單機支持上千個容器 | 一般幾十個 |
1.3,Docker 架構
runc 是一個 Linux 命令行工具,用於根據 OCI容器運行時規範 創建和運行容器。
containerd 是一個守護程式,它管理容器生命周期,提供了在一個節點上執行容器和管理鏡像的最小功能集。
1.4,為什麼用 Docker
Docker 作為一種新的虛擬化技術,跟傳統的虛擬化技術相比具有眾多的優勢:
- 更高效的利用系統資源:不需要進行硬體虛擬以及運行完整操作系統等額外開銷,Docker 對系統資源的利用率更高。
- 更快速的啟動時間:Docker 容器應用直接運行於宿主內核,不需要啟動完整的操作系統,所以啟動時間可做到秒級的啟動時間。
- 一致的運行環境:Docker 鏡像提供了除內核外完整的運行時環境,確保開發環境、測試環境、生產環境的一致性。
- 持續交付和部署:開發人員可以通過 Dockerfile 來進行鏡像構建,並結合持續集成(Continuous Integration) 系統進行集成測試,而運維人員則可以直接在生產環境中快速部署該鏡像,甚至結合持續部署(Continuous Delivery/Deployment) 系統進行自動部署。
- 更輕鬆的遷移:Docker 可以在很多平臺上運行,無論是物理機、虛擬機、公有雲、私有雲,甚至是筆記本,其運行結果是一致的。
- 更輕鬆的維護和擴展。
二,Docker 基本概念
Docker 三個基本概念:
- 鏡像(Image)
- 容器(Container)
- 倉庫(Repository)
2.1,鏡像
操作系統分為內核和用戶空間。對於 Linux 而言,內核啟動後,會掛載 root 文件系統為其提供用戶空間支持。而 Docker 鏡像(Image),就相當於是一個 root 文件系統。比如官方鏡像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系統的 root 文件系統。
Docker 鏡像 是一個特殊的文件系統,除了提供容器運行時所需的程式、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(如匿名捲、環境變數、用戶等)。鏡像 不包含 任何動態數據,其內容在構建之後也不會被改變。
Docker 鏡像並非是像一個 ISO
那樣的打包文件,鏡像只是一個虛擬的概念,其實際體現並非由一個文件組成,而是由一組文件系統組成,或者說,由多層文件系統聯合組成。其被設計為分層存儲的架構,鏡像構建時,會一層層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在自己這一層。分層存儲的特征還使得鏡像的復用、定製變的更為容易。甚至可以用之前構建好的鏡像作為基礎層,然後進一步添加新的層,以定製自己所需的內容,構建新的鏡像。
2.2,容器
鏡像(Image)和容器(Container)的關係,類似面向對象程式設計中的類和實例的關係。可以把 Docker容器(Container) 看做是一個簡易版的 Linux 環境(包括 root 用戶許可權、進程空間、用戶空間和網路空間等)和運行在其中的應用程式。它可以被啟動、開始、停止、 刪除。
容器的實質是進程,但與直接在宿主執行的進程不同,容器進程運行於屬於自己的獨立的 命名空間。因此容器可以擁有自己的 root 文件系統、自己的網路配置、自己的進程空間,甚至自己的用戶 ID 空間。容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立於宿主的系統下操作一樣。
容器和鏡像一樣都是使用分層存儲,每一個容器運行時,是以鏡像為基礎層,在其上創建一個當前容器的存儲層,我們可以稱這個為容器運行時讀寫而準備的存儲層為容器存儲層。
2.3,倉庫
鏡像構建完成後,可以很容器的在當前宿主主機上運行,但是如果需要在其他伺服器上使用這個鏡像,我們就需要一個集中的存儲、分發鏡像的服務,Docker Registry 就是這樣的服務。
一個 Docker Registry 中可以包含多個 倉庫(Repository);每個倉庫可以包含多個 標簽(Tag);每個標簽對應一個鏡像。
通常,一個倉庫會包含同一個軟體不同版本的鏡像,而標簽就常用於對應該軟體的各個版本。我們可以通過 <倉庫名>:<標簽>
的格式來指定具體是這個軟體哪個版本的鏡像。如下所示:
registry.sensetime.com/kestrel_tatraffic/kestrel_tatraffic:kestrel_cuda11_1.2.21_opencv3.4.13_with_ffmpeg
Docker倉庫(Registry) 分為公開倉庫(Public)和私有倉庫(Private)兩種形式。最大的公開倉庫是 Docker Hub, 存放了數量龐大的鏡像供用戶下載。國內的公開倉庫包括 Docker Pool 等,可以提供大陸用戶更穩定快速的訪問。私有倉庫是指用戶在本地搭建的私有 Docker Registry。
三,Docker 使用
3.1,Docker 服務
安裝 Docker 這裡不做介紹。以下是 Linux 系統下,一些 docker 使用命令:
1,查看 Docker 服務狀態:使用 systemctl status docker
命令查看 Docker 服務的狀態。其中 Active: active (running) 即表示 Docker 服務為正在運行狀態。
2,停止 Docker 服務:使用 systemctl stop docker
命令。
3,啟動 Docker 服務:使用 systemctl start docker
命令。
4,重啟 Docker 服務:使用 systemctl restart docker
命令。
5,測試 Docker 是否安裝正確。
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
7050e35b49f5: Pull complete
Digest: sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
3.2,下載與使用Docker公共鏡像(Images)
1,使用 docker search 命令從 Docker Repo 搜索 Dokcer 可用的鏡像。示例命令:docker search ubuntu18.04
。
2,使用 docker image pull 命令從 Docker Repo 獲取指定的 Dokcer鏡像(Images)。示例命令: docker image pull docker.io/hello-world
。拉取名為 docker.io/hello-world 的鏡像。
3,使用 docker image ls 命令查看本地的 Dokcer 鏡像(Images)。
4,使用 docker run 命令運行 Dokcer 鏡像(Images)。示例命令:docker run hello-world
。
5,使用 docker info 命令,查看當前 docker容器 的所有的信息。
6,使用 docker version 查看容器的版本信息。
$ dockerd --versio # 這個命令查看 docker 版本更簡單
Docker version 19.03.13, build 4484c46d9d
四,Docker 鏡像命令
Docker鏡像(Images) 也可以理解為是一個用於創建 Docker容器(Container) 的靜態模板。一個 Docker鏡像(Images) 可以創建很多 Docker容器(Container)。
Docker 鏡像常用命令如下:
命令 | 描述 |
---|---|
docker commit | 創建鏡像。 |
docker images | 查看鏡像信息。 |
docker load | 導入鏡像。 |
docker pull | 拉取 Docker 鏡像。 |
docker push | 上傳鏡像。 |
docker rmi | 刪除鏡像。 |
docker save | 導出鏡像。 |
docker search | 在 Docker Hub 搜索鏡像。 |
docker tag | 為鏡像打標簽。 |
五,Docker 容器命令
5.1,docker run 命令
通過 docker run 命令可以基於鏡像新建一個容器並啟動,語法如下:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
其他常用容器管理命令如下:
# 新建容器並啟動
$ docker run [鏡像名/鏡像ID]
# 啟動已終止容器
$ docker start [容器ID]
# 列出本機運行的容器
$ docker ps
# 停止運行的容器
$ docker stop [容器ID]
# 殺死容器進程
$ docker kill [容器ID]
# 重啟容器
$ docker restart [容器ID]
docker run命令語法
1, docker run 命令常用選項:可通過 docker run --help 命令查看全部內容。
選項 | 說明 |
---|---|
-d, --detach=false | 指定容器運行於前臺還是後臺,預設為 false。 |
-i, --interactive=false | 打開 STDIN,用於控制台交互。 |
-t, --tty=false | 分配 tty 設備,該可以支持終端登錄,預設為 false。 |
-u, --user="" | 指定容器的用戶。 |
-a, --attach=[] | 登錄容器(必須是以 docker run -d 啟動的容器)。 |
-w, --workdir="" | 指定容器的工作目錄。 |
-c, --cpu-shares=0 | 設置容器 CPU 權重,在 CPU 共用場景使用。 |
-e, --env=[] | 指定環境變數,容器中可以使用該環境變數。 |
-m, --memory="" | 指定容器的記憶體上限。 |
-P, --publish-all=false | 指定容器暴露的埠。 |
-p, --publish=[] | 指定容器暴露的埠。 |
-h, --hostname="" | 指定容器的主機名。 |
-v, --volume=[] | 給容器掛載存儲捲,掛載到容器的某個目錄。 |
–volumes-from=[] | 給容器掛載其他容器上的捲,掛載到容器的某個目錄。 |
–cap-add=[] | 添加許可權。 |
–cap-drop=[] | 刪除許可權。 |
–cidfile="" | 運行容器後,在指定文件中寫入容器 PID 值,一種典型的監控系統用法。 |
–cpuset="" | 設置容器可以使用哪些 CPU,此參數可以用來容器獨占 CPU。 |
–device=[] | 添加主機設備給容器,相當於設備直通。 |
–dns=[] | 指定容器的 dns 伺服器。 |
–dns-search=[] | 指定容器的 dns 搜索功能變數名稱,寫入到容器的 /etc/resolv.conf 文件。 |
–entrypoint="" | 覆蓋 image 的入口點。 |
–env-file=[] | 指定環境變數文件,文件格式為每行一個環境變數。 |
–expose=[] | 指定容器暴露的埠,即修改鏡像的暴露埠。 |
–link=[] | 指定容器間的關聯,使用其他容器的 IP、env 等信息。 |
–lxc-conf=[] | 指定容器的配置文件,只有在指定 --exec-driver=lxc 時使用。 |
–name="" | 指定容器名字,後續可以通過名字進行容器管理,links 特性需要使用名字。 |
–net=“bridge” | 器網路設置: 1. bridge 使用 docker daemon 指定的網橋。 2. host //容器使用主機的網路。 3. container:NAME_or_ID >//使用其他容器的網路,共用 IP 和 PORT 等網路資源。 4. none 容器使用自己的網路(類似–net=bridge),但是不進行配置。 |
–privileged=false | 指定容器是否為特權容器,特權容器擁有所有的 capabilities。 |
–restart=“no” | 指定容器停止後的重啟策略: 1. no:容器退出時不重啟。 2. on-failure:容器故障退出(返回值非零)時重啟。 3. always:容器退出時總是重啟。 |
–rm=false | 指定容器停止後自動刪除容器(不支持以 docker run -d 啟動的容器)。 |
–sig-proxy=true | 設置由代理接受並處理信號,但是 SIGCHLD、SIGSTOP 和 SIGKILL 不能被代理。 |
示例:kestrel 人群等 sdk 使用運行容器的腳本如下:
export BUILDER=registry.sensetime.com/kestrel_tatraffic/kestrel_tatraffic:kestrel_cuda11_1.2.21_opencv3.4.13_with_ffmpeg
# -t 選項讓Docker分配一個偽終端(pseudo-tty)並綁定到容器的標準輸入上, -i 則讓容器的標準輸入保持打開。
# --rm 指定容器停止後自動刪除容器
# --net=host 容器使用主機的網路
# --ipc 要使用的 IPC 模式
# --ipc=host
# -e 指定環境變數,容器中可以使用
# --privileged 指定容器是否為特權容器,特權容器擁有所有的 capabilities
# -u 指定容器的用戶為 root
# -entrypoint=bash 覆蓋 image 的入口點
# -v 給容器掛載存儲捲,掛載到容器的 /kestrel_baggage
# 指定容器的工作目錄為 /kestrel_baggage
# ${BUILDER} 為運行的鏡像
docker run --gpus '"device=0"' -it --rm --net=host --ipc=host \
-e DISPLAY=$DISPLAY \
--privileged \
-e XAUTHORITY=$XAUTH \
-u root \
--entrypoint=bash \
--ulimit core=-1 \
--security-opt seccomp=unconfined \
-v ${PWD}:/kestrel_baggage \
-w /kestrel_baggage \
${BUILDER}
2,Docker互動式運行的語法為:docker run -i -t IMAGE [COMMAND] [ARG]
。Docker互動式運行,即 Docker 啟動直接進入 Docker 鏡像內部。
3,使用 docker ps
命令,查看正在運行的 docker。