掘金小冊 - 開發者必備的 Docker 指南
Docker 基礎-映象&容器&網路&儲存
知識脈絡
- 安裝 Docker
- 映象&容器
- 網路
- 儲存
- Dockerfile
- docker compose
- docker hub
1. 安裝 Docker
官網安裝教程:https://docs.docker.com/install/
2. 映象&容器
2.1 概念
映象: 我們可以理解為 包含應用程式以及其相關依賴的一個基礎檔案系統. 從另一個角度看, Docker 映象其實是由基於 UnionFS 檔案系統的一組映象層依次掛載而得,而每個映象層包含的其實是對上一映象層的修改,這些修改其實是發生在容器執行的過程中的.
容器: 容器是基於 映象 建立出來的。 可以將映象理解為 類, 將容器理解為 類的例項.
2.2 容器的生命週期
Created、Running、Paused、Stopped、Deleted
- Created: 容器已經被建立,容器所需的相關資源已經準備就緒, 但容器中的程式還未處於執行狀態.
- Running: 容器正在執行, 也就是容器中的應用正在執行.
- Paused: 容器已暫停, 表示容器中的所有程式都處於暫停 ( 不是停止 ) 狀態.
- Stopped: 容器處於停止狀態, 佔用的資源和沙盒環境都依然存在, 只是容器中的應用程式均已停止.
- Deleted: 容器已刪除, 相關佔用的資源及儲存在 Docker 中的管理資訊也都已釋放和移除.
2.3 容器與容器的主程式
容器的啟動, 本質上可以理解為這個程式的啟動, 而容器的停止也就意味著這個程式的停止, 反過來理解亦然.
2.4 寫時複製機制
透過映象執行容器時, 並不是馬上就把映象裡的所有內容複製到容器所執行的沙盒檔案系統中, 而是利用 UnionFS 將映象以只讀的方式掛載到沙盒檔案系統中. 只有在容器中發生對檔案的修改時, 修改才會體現到沙盒環境上.
2.5 相關命令
命令 | 解釋 | 引數解釋 |
---|---|---|
docker pull | 拉取映象 | - |
docker images | 檢視系統內的映象 | - |
docker inspect IMAGE_NAME | 檢視映象的詳細資訊 | - |
docker rmi IMAGE_NAME/IMAGE_ID ... | 刪除映象 | - |
docker create --name CUSTOM_IMAGE_NAME IMAGE_NAME:TAG | 建立容器 | --name: 指定容器名稱 |
docker start IMAGE_NAME/IMAGE_ID | 啟動容器 | - |
docker restart IMAGE_NAME/IMAGE_ID | 重啟容器 | - |
docker run --name CUSTOM_IMAGE_NAME -d / --detach IMAGE_NAME:TAG | 建立並啟動容器 | -d / --detach: 容器後臺執行 |
docker stop IMAGE_NAME/IMAGE_ID | 停止容器 | - |
docker rm [-f / --force] [-v] IMAGE_NAME/IMAGE_ID | 刪除容器 | -f / --force: 強制刪除容器, -v: 刪除資料卷 |
docker ps [-a / --all] | 檢視正在執行的容器 | 加上 -a / --all 是檢視所有容器 |
docker exec -it IMAGE_NAME/IMAGE_ID bash | 進入容器 | -i (--interactive)表示保持我們的輸入流, -t ( --tty ) 表示啟用一個偽終端 |
引數 | 解釋 |
---|---|
--name | 指定容器名稱 |
--network | 指定網路 |
-p \:\:\ | 埠對映 |
-d / --detach | -d / --detach: 容器後臺執行 |
-it | -i (--interactive)表示保持我們的輸入流, -t ( --tty ) 表示啟用一個偽終端 |
--rm | 容器停止後就自動刪除 |
例子:
docker run --name NGINX --network bridge -p 80:80 -d nginx:1.12
docker run -it --name NGINX --network bridge -p 80:80 nginx:1.12 bash
docker exec -it NGINX bash
3. 網路
3.1 概念
在 Docker 網路中,有三個比較核心的概念:沙盒 ( Sandbox )、網路 ( Network )、端點 ( Endpoint )
- 沙盒 提供了容器的虛擬網路棧, 也就是之前所提到的埠套接字、IP 路由表、防火牆等的內容. 其實現隔離了容器網路與宿主機網路,形成了完全獨立的容器網路環境.
- 網路 可以理解為 Docker 內部的虛擬子網, 網路內的參與者相互可見並能夠進行通訊. Docker 的這種虛擬網路也是於宿主機網路存在隔離關係的, 其目的主要是形成容器間的安全通訊環境.
- 端點 是位於容器或網路隔離牆之上的洞, 其主要目的是形成一個可以控制的突破封閉的網路環境的出入口. 當容器的端點與網路的端點形成配對後, 就如同在這兩者之間搭建了橋樑, 便能夠進行資料傳輸了.
目前 Docker 官方為我們提供了五種 Docker 網路驅動,分別是:Bridge Driver、Host Driver、Overlay Driver、MacLan Driver、None Driver
其中, Bridge 網路是 Docker 容器的預設網路驅動, 簡而言之其就是透過網橋來實現網路通訊 (網橋網路的實現可以基於硬體, 也可以基於軟體 ). 而 Overlay 網路是藉助 Docker 叢集模組 Docker Swarm 來搭建的跨 Docker Daemon 網路, 我們可以透過它搭建跨物理主機的虛擬網路, 進而讓不同物理機中執行的容器感知不到多個物理機的存在.
3.2 容器互聯
要讓一個容器連線到另外一個容器, 我們可以在容器透過 docker create
或 docker run
建立時透過 --link
選項進行配置.
$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
$ sudo docker run -d --name webapp --link mysql webapp:latest
這樣在 webapp 中連線 mysql 時就可以: String url = "jdbc:mysql://mysql:3306/webapp";
, 或者我們可以在 --link
時定義別名, 使用 --link <name>:<alias>
的形式:
$ sudo docker run -d --name webapp --link mysql:database webapp:latest
這樣在 webapp 中連線 mysql 時就可以: String url = "jdbc:mysql://database:3306/webapp";
3.3 暴露埠
在容器建立時埠暴露的方法是藉助 --expose
這個選項
$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 13306 --expose 23306 mysql:5.7
3.4 管理網路
容器能夠互相連線的前提是兩者同處於一個網路中 ( 這裡的網路是指容器網路模型中的網路 )
當我們啟動 Docker 服務時,它會為我們建立一個預設的 bridge 網路,而我們建立的容器在不專門指定網路的情況下都會連線到這個網路上
命令 | 解釋 | 引數解釋 |
---|---|---|
docker network create -d bridge NETWORK_NAME | 建立網路 | -d: 指定網路驅動 |
docker network ls / list | 檢視已存在的網路 | - |
docker network rm NETWORK_NAME | 刪除網路 | - |
4. 儲存
我們直接在 容器
內做的修改(也就是對 沙盒檔案系統
做出的修改)是無法持久化儲存的, 如果 Docker 容器刪除了, 你的修改也就沒了. 所以我們不要在容器內做修改. 我們只需要將宿主作業系統中, 檔案系統裡的檔案或目錄掛載到容器中, 便能夠讓容器內外共享這個檔案.
Docker 提供了三種適用於不同場景的檔案系統掛載方式:Bind Mount、Volume和 Tmpfs Mount
-
Bind Mount 能夠直接將宿主作業系統中的目錄和檔案掛載到容器內的檔案系統中, 透過指定容器外的路徑和容器內的路徑, 就可以形成掛載對映關係, 在容器內外對檔案的讀寫, 都是相互可見的.
-
Volume 也是從宿主作業系統中掛載目錄到容器內, 只不過這個掛載的目錄由 Docker 進行管理, 我們只需要指定容器內的目錄, 不需要關心具體掛載到了宿主作業系統中的哪裡.
-
Tmpfs Mount 支援掛載系統記憶體中的一部分到容器的檔案系統裡, 不過由於記憶體和容器的特徵, 它的儲存並不是持久的, 其中的內容會隨著容器的停止而消失.
4.1 掛載檔案到容器
使用 -v
或 --volume
來掛載宿主作業系統目錄的形式是 -v <host-path>:<container-path>
或 --volume <host-path>:<container-path>
, 其中 host-path 和 container-path 分別代表宿主作業系統中的目錄和容器中的目錄. 為了避免混淆, Docker 這裡強制定義目錄時必須使用絕對路徑, 不能使用相對路徑.
sudo docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html nginx:1.12
4.2 只讀掛載
:ro
sudo docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html:ro nginx:1.12
4.3 掛載臨時檔案目錄
Tmpfs Mount 是一種特殊的掛載方式, 它主要利用記憶體來儲存資料. 由於記憶體不是永續性儲存裝置, 所以其帶給 Tmpfs Mount 的特徵就是臨時性掛載. 掛載臨時檔案目錄要透過 --tmpf
這個選項來完成.
sudo docker run -d --name webapp --tmpfs /webapp/cache webapp:latest
4.4 使用資料卷
使用 -v
或 --volume
選項來定義資料卷的掛載.
sudo docker run -d --name webapp -v /webapp/storage webapp:latest
使用 -v <name>:<container-path>
來命名資料卷
sudo docker run -d --name webapp -v appdata:/webapp/storage webapp:latest
由於 -v
選項既承載了 Bind Mount 的定義, 又參與了 Volume 的定義, 所以其傳參方式需要特別留意. 前面提到了, -v
在定義繫結掛載時必須使用絕對路徑, 其目的主要是為了避免與資料卷掛載中命名這種形式的衝突.
4.5 資料卷命令
命令 | 解釋 |
---|---|
docker volume ls | 列出資料卷 |
docker volume create VOLUME_NAME | 建立資料卷 |
docker volume rm VOLUME_NAME | 刪除資料卷 |
4.6 資料卷容器
sudo docker create --name appdata -v /webapp/storage ubuntu
# 引用資料卷容器 --volumes-from
sudo docker run -d --name webapp --volumes-from appdata webapp:latest
4.7 備份和遷移資料卷
# 提前在宿主機器上 新建 /backup 資料夾
sudo docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar cvf /backup/backup.tar /webapp/storage
5. docker commit
修改容器, 儲存修改為新的映象
啟動一個 nginx 容器, 修改, 比如 安裝 vim, 退出.
docker commit -a 'o9' -m 'add vim' nginx:1.12 o9-nginx:1.12
6. docker hub
本作品採用《CC 協議》,轉載必須註明作者和本文連結