一、Docker 數據管理
Docker 持久化數據有兩種方式:
- 使用數據卷:更安全,和主機耦合度低
- 將主機的目錄掛載到容器中:更方便,主機和容器可以很方便地交換數據。
數據卷相關的命令:
docker volume create <volume name> # 新建數據卷
docker volume ls # 列出所有數據卷
docker volume inspect <volume name> # 查看數據卷信息
docker volume rm <volume name> # 刪除數據卷
docker volume prune # 清除所有未掛載的數據卷
數據卷/文件夾的掛載命令:
# 1. 掛載數據卷
docker run -d -P \
--name web \
# -v my-vol:/wepapp \
--mount source=my-vol,target=/webapp \
training/webapp \
python app.py
# 2. 掛載宿主機的文件夾
docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp:ro \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp \
python app.py
# P.S. 以前是使用 -v 參數,現在推薦使用 --mount
數據卷的備份恢復
數據卷的備份、恢復與內容查看,都必須通過容器進行!
官方的推薦方法是,啟動一個中間容器,掛載上對應的數據卷。
然后進入該容器查看數據卷內容,使用 tar
命令進行數據卷內容的備份(打包成 tar.gz)/恢復(將 tar.gz 解壓到數據卷中)。
二、網絡
1. 外部訪問容器
使用端口映射 -p <宿主機端口>:<容器端口>
(該參數可重復多次使用),或者 -P
將容器 EXPOSE
出來的端口隨機映射到宿主機。
2. 容器之間的互聯
比較方便的方案,是將容器加入自定義的 Docker 網絡以實現多容器互聯。
-
新建自定義網絡
docker network create --driver=bridge <net name> # 新建自定義網絡,使用 bridge 模式
-
在運行容器時,通過
docker run --network=<net name> --name <container name> ...
將容器添加到該自定義網絡
然后在其中一個容器中ping <container name>
,該名稱會直接被解析到對應的容器 ip。這樣,容器之間就能以容器名稱為 hostname 互聯。 -
通過
docker container inspect
可獲知容器在 docker0 上的 ip 地址,容器之間可以通過該 ip 通信。- 缺點:ip 是動態分配的!每次都要手動配。。
如果容器較多,推薦使用 docker-compose 進行編排。
3. 容器訪問宿主機網絡
從 Docker 對這種連接方式的支持來看,顯然是很不推薦用戶這么干的。
但是對個人用戶而言,從容器訪問宿主機,我覺得還是個挺常見的需求。
可用方法如下:
- 通過宿主機的公網 ip 訪問宿主機
- 缺點:宿主機需要向公網開放對應的端口。
- 在運行容器時指定
--network=host
,容器與宿主機共用網絡- 缺點:容器與宿主機耦合度過高。而且可能出現端口沖突。
- 通過
ip addr show docker0
查看宿主機在網橋docker0
上的 ip 地址(linux 下一般為172.17.0.1
),容器可通過該 ip 訪問宿主機。- 缺點:不同宿主機在
docker0
上可能具有不同的 ip,需要運行時手動配置。
- 缺點:不同宿主機在
- 通過 shell 腳本獲取 host ip:參見 Docker for Linux - Support host.docker.internal DNS name to host
- 等 special DNS record for host.docker.internal + gateway.docker.internal 被 merged,就能直接使用
host.docker.internal
訪問宿主機了。
三、使用 nsenter 進入容器的網絡 namespace
查看 Docker 容器的連接數:
docker inspect -f '{{.State.Pid}}' <containerid> # 查找到容器的 pid
sudo nsenter -t <pid> -n netstat | grep ESTABLISHED # 通過 pid 檢索所有連接
三、系統權限
一個系統上的 docker 容器,默認情況下是無法修改系統的公共內核參數的。這是一種隔離機制。
如果某個容器抽風把系統參數改得一團糟,那所有容器都會崩潰,沒有人會希望碰到這種情況。
但是有的時候,我們確實需要在容器內修改整個系統的某些參數。比如在測試系統的時候,我們系統直接修改整個系統的時間,然后查看我們的應用能否應對這種問題。
為了滿足這種需求,Docker 提供了一組參數用來給容器設置額外的權限。
Docker 容器的隔離是基於 Linux 的 Capability 機制實現的, Linux 的Capability 機制允許你將超級用戶相關的高級權限划分成為不同的小單元. 目前 Docker 容器默認只用到了以下的 Capability:
CHOWN,
DAC_OVERRIDE,
FSETID,
FOWNER,
MKNOD,
NET_RAW,
SETGID,
SETUID,
SETFCAP,
SETPCAP,
NET_BIND_SERVICE,
SYS_CHROOT,
KILL,
AUDIT_WRITE
使用 --cap-add, --cap-drop 可以添加或禁用特定的權限。
比如容器若要修改系統時間,就要求它擁有 SYS_TIME 權限,所以我們在運行容器時需要添加參數 --cap-add SYS_TIME
。
然后在容器里運行 date --set "time-string"
,就能修改掉整個系統的時間。
P.S.
--privileged
參數也可以達到開放權限的作用, 與--cap-add
的區別就是,--privileged
是將所有權限給容器,這相當危險!
四、docker-compose
用於編排多個容器,管理容器集群之間的協作關系。
國內安裝鏡像:docker: install-compose
常用命令
docker-compose up
:- (推薦在測試時使用)新建並啟動容器,聚合輸出容器組中所有容器的 logs,命令結束時(ctrl+c),會 stop 掉整個容器組。
- (在生產環境下要添加該選項!)在
-d
模式(detached,分離模式)下運行。與默認行為的差別在與,命令結束后,容器組中的容器仍然會繼續運行。
docker-compose start
: 啟動終止的容器組。
docker-compose 大部分命令都和 docker 完全類似。只是它是集群版本。