Docker筆記
1. Docker簡介
-
開源的應用容器引擎
-
打包環境和應用到一個輕量級,可移植的容器中,發布到任何 Linux 機器上,規避了軟體跨環境遷移的問題
-
沙箱機制,相互隔離
1.1 安裝
sudo apt install docker-ce
1.2 架構
-
守護進程(daemon):後台服務,管理一個 Docker 進程
-
鏡像(image):相當於一個 root 文件系統,打包了環境和應用
-
容器(container):鏡像運行時的實體,可以被創建,啟動,暫停, 停止,刪除
-
倉庫(repository):保存鏡像文件
2. Docker命令
2.1 服務(守護進程)相關
- 啟動
sudo systemctl start docker
- 查看
sudo systemctl status docker
- 停止
sudo systemctl stop docker
- 重啟
sudo systemctl restart docker
2.2 鏡像相關
- 查看
sudo docker images
- 搜索
# 查看具體版本號需要去 hub.docker.com
sudo docker search ubuntu
- 拉取
# 配置阿里雲加速://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["加速地址"]
}
sudo systemctl daemon-reload
sudo systemctl restart docker
# 拉取鏡像
sudo docker pull ubuntu[:版本]
- 刪除
sudo docker rmi ubuntu[:版本]
2.3 容器相關
- 查看
# 要查看所有包括已停止運行的容器:加上參數 -a
sudo docker ps
- 創建
# -i:保持STDIN打開,-t:交互模式,bash:自定義進入容器後執行的命令
# -it 啟動的容器稱為互動式容器,exit 命令退出後容器會自動停止
sudo docker run -it --name u1 ubuntu[:版本] bash
# -d:後台創建容器,不會立即進入
# -id 啟動的容器稱為守護式容器,exit 退出時容器也不會自動停止
sudo docker run -id --name u1 ubuntu[:版本]
- 進入
# 只能進入正在運行的容器
sudo docker exec -it u1 bash
- 啟動
# 這種方式啟動容器後 exit 退出時也不會自動停止
sudo docker start u1
- 停止
sudo docker stop u1
- 刪除
# 不能刪除正在運行的容器
sudo docker rm u1
- 查看資訊
sudo docker inspect u1
3. Docker數據卷
3.1 簡介
- 宿主機中的一個目錄(或文件),與容器內目錄(文件)綁定後,同步它們的數據
- 可以被多個容器同時掛載,一個容器也可以掛載多個數據卷
- 數據持久化與數據交換
3.2 配置數據卷
# 創建啟動容器時,-v 參數設置
# 容器內目錄必須是絕對路徑,宿主機目錄可以相對,但相對的是 /var/lib/docker/volumes/,並不是當前路徑
# 目錄不存在會自動創建,而文件不存在時會被當成目錄創建並掛載
# 可用多個 -v 掛載多個
sudo docker run ... -v 宿主目錄(文件):容器內目錄(文件) ... --name u1 ubuntu[:版本]
3.3 配置數據卷容器
配置一個專門的容器來掛載數據卷,其他容器掛載這個容器(這時候相當於掛載同一個數據卷)來交換數據
sudo docker run ... -v 宿主目錄(文件):容器內目錄(文件) ... --name u1 ubuntu[:版本]
# 其他容器掛載 u1
sudo docker run ... --volumes-from u1 --name u2 ubuntu[:版本]
sudo docker run ... --volumes-from u1 --name u3 ubuntu[:版本]
4. Docker應用部署
4.1 搜索並拉取鏡像
sudo docker search mysql
sudo docker pull mysql:5.7
4.2 MySQL部署
# 宿主機創建MySQL目錄用來存儲數據資訊
mkdir mysql
cd mysql
# 埠映射 宿主機:容器
sudo docker run -id \
-p 3306:3306 \
-v $PWD/conf.d:/etc/mysql.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=111 \
--name m1 mysql:5.7
4.3 Nginx部署
mkdir nginx
cd nginx
# 如果需要默認配置,可先啟動一個容器將默認配置複製一份,否則宿主機空文件掛載後會覆蓋容器內文件
# sudo docker cp n1:/etc/nginx/nginx.conf nginx.conf
sudo docker run -id \
-p 80:80 \
-v $PWD/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/conf.d:/etc/nginx/conf.d \
-v $PWD/logs:/var/log/nginx \
--name n1 nginx
5. Docker鏡像製作
5.1 Docker鏡像原理
- Docker鏡像是由特殊的 文件系統 疊加 而成
- 最底端使用宿主機的bootfs
- 第二層是 rootfs,被稱為基礎鏡像
- 最頂層為對外鏡像名,下層鏡像稱為上層鏡像的父鏡像,下載時會把父鏡像一併下載
- 統一文件系統將不同層整合成了一個文件系統,隱藏了多層的存在
- 鏡像是只讀的,從一個鏡像啟動容器時,會在頂層載入一個讀寫文件系統作為容器
5.2 方式一:容器轉鏡像
這種方式並不常用,因為打包後體積巨大不利於傳遞。
# 原容器中掛載的目錄(文件)不會被提交到鏡像
sudo docker commit 容器名(id) 鏡像名[:版本號]
# 鏡像打包
sudo docker save -o 文件名 鏡像名[:版本號]
# 鏡像還原
sudo docker load -i 文件名
5.3 方式二:Dockerfile
- 包含多條指令的文本文件
- 每條指令構建一層,基於基礎鏡像
- 提供完全一致的環境的構建方法
- 參照 hub.docker.com 上相關鏡像的寫法
- 構建
# 最後的 . 表示當前路徑,是上下文目錄,構建時會將路徑下所有文件發給Docker引擎供 COPY ADD 等命令調用
# 如果配置文件名不為 Dockerfile,可用 -f 指定文件名
sudo docker build -t 新鏡像名 .
5.4 Dockerfile常用關鍵字
- FROM:基於哪個基礎鏡像
- MAINTAINER:鏡像維護者的姓名和郵箱地址
- WORKDIR:指定運行目錄,為後續的 RUN、CMD、COPY、ADD 等命令配置工作目錄,默認 /
- COPY:將宿主機的文件拷貝到鏡像中去(原文件必須在build命令最後指定的路徑內)
- ADD:和COPY一樣,並且還可以解壓縮,或者從url拷貝文件到鏡像中
- RUN:構建鏡像時運行的shell命令,由於DockerFile每條指令都會堆疊一層鏡像,所以最好使用 \ 換行和 && 連接命令來減少體積
- EXPOSE:指定鏡像暴露出來的埠
- CMD:容器運行時默認執行的shell命令(多個CMD只有最後一個生效)
- VOLUME:聲明容器內多個路徑為匿名卷,run容器時若沒有指定宿主機目錄與其關聯,則自動在宿主機創建目錄與其關聯,目的是防止容器運行時產生太多數據,如 log
- ENV:指定環境變數
- USER:使用哪個用戶啟動,默認root
- ENTRYPOINT:和CMD一樣,但是可以追加(必須使用exec格式:ENTRYPOINT [./entrypoint.sh,參數1,參數2……])
- LABEL:標籤
- ONBUILD:當構建一個父鏡像時,父鏡像被子鏡像繼承時,ONBUILD被觸發
6. 服務編排(Docker Compose)
微服務架構系統中一般包含多個微服務,每個微服務一般會部署多個實例,如果手動管理工作量就會很大:
- 要構建或拉取鏡像
- 要創建多個容器
- 要管理這些容器
服務編排就是按照一定的規則批量管理容器的方法。Docker Compose 是一個編排多容器分散式部署的工具,提供命令集管理容器化應用的完整生命周期,使用步驟:
- 利用 DockerFile 定義運行環境鏡像
- 使用 docker-compose 配置文件定義組成應用的各服務
- 運行 docker-compose up 啟動應用
6.1 安裝
sudo apt install docker-compose
6.2 編排一個 Nginx+Flask 項目
- 創建工作目錄
mkdir project
cd project
# 創建nginx個人配置目錄,一會兒做映射
mkdir -p nginx/conf.d
- 編寫docker-compose配置文件
version: '3'
services:
# 定義一個容器
nginx1:
# 可以自定義容器名
container_name: main_nginx
image: nginx
ports:
- "80:80"
# 鏈接到另一個容器後便可以直接訪問
links:
- flask1
# 這裡簡單起見對默認配置不做修改,僅掛載自定義配置
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
flask1:
container_name: main_flask
# 可以基於一份Dockerfile製作鏡像並創建容器,如果同時指定image會以它命名鏡像
# 這裡假設已經在當前目錄下寫好了flask鏡像的Dockerfile
build:
context: .
dockerfile: ./Dockerfile
image: img_flask
# 暴露埠,並沒有與宿主機做映射,只允許被鏈接容器訪問
expose:
- "8000"
# 如果容器內沒有前台常駐進程,構建完後會立即退出,加上tty參數分配一個偽終端
# tty: true
- 編寫Nginx程式配置 ./nginx/conf.d/flask1.conf
server {
listen 80; # 監聽80埠來自外部的請求
server_name _; # 如果映射了域名,可以代替_
# 為HTTP規則 / 設置轉發
location / {
proxy_pass //flask1:8000; # 轉發到本地埠
}
}
- 啟動
# 如果配置文件名不為 docker-compose.yml,可用 -f 指定文件名
# 後台啟動 -d
sudo docker-compose up
- 查看所有容器狀態
sudo docker-compose ps
- 停止容器
# 可通過 sudo docker-compose start 再次啟動
sudo docker-compose stop
# 刪除所有停止狀態的容器
sudo docker-compose rm
# 停止並刪除容器,網路
# --rmi all/local (刪除compose文件中定義的所有鏡像)/(刪除鏡像名為空的鏡像)
# -v 刪除已經在compose文件中定義的和匿名的掛載在容器上的數據卷
sudo docker-compose down