Docker 安裝
Docker 可支持在 Mac、Windows、Linux 系統上安裝,但是在 Windows 系統中 Docker 的安裝包目前僅有 win10 專業版和企業版的。win10 家庭版可以采用開啟 Hyper-V 偽裝成專業版繞過安裝檢測。還有一種方式是通過 Docker toolbox 來安裝(適用於 win7/win8/win10 家庭版),下載地址:http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/ (本質上相當於安裝了一個 linux 虛擬機)。
Docker 分為社區版和專業版,社區版本的官網:https://docs.docker.com/install/overview/
1)安裝
環境說明:
這里以 Centos 8 安裝和使用 Docker 為演示示例(Docker 官網關於 centos 上如何安裝 Docker 的文章如下:https://docs.docker.com/install/linux/docker-ce/centos/)
Centos 8 安裝 Docker,在保證可以通外網的情況下,通過 yum 安裝(yum 是 Centos 和 Redhat 下便捷的管理安裝的軟件,如果是 ubuntu 系統則可以通過 apt)。
1)安裝前置包
yum install -y yum-utils device-mapper-persistent-data lvm2 libseccomp-devel
2)安裝 docker 的 yum 源
# 可以使用官方源,這個安裝過程可能會比較慢
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 或者使用阿里雲的鏡像源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
docker-ce 是 Docker 的發行版本,yum 安裝的目標就是 docker-ce。
3)使用 yum list 查看可安裝版本
yum list docker-ce --showduplicates
yum install –y docker-ce-3:19.03.15-3.el8
這里選擇 19.03 版本,如果不加版本號,會默認安裝最新版本。
2)啟動
Docker 引擎啟停操作:
# 啟動
systemctl start docker
# 重啟
systemctl restart docker
# 開機自啟動
systemctl enable docker
# 運行狀態
systemctl status docker
3)鏡像加速器
默認情況下從 docker hub 上下載 docker 鏡像的速度太慢,因此一般都會配置鏡像加速器:
- USTC:中科大鏡像加速器(https://docker.mirrors.ustc.edu.cn)
- 阿里雲
- 網易雲
- 騰訊雲
# 添加 registry-mirrors
vim /etc/docker/daemon.json
# 內容
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
# 重載 docker 的配置文件
systemctl daemon-reload
# 重啟 Docker
systemctl restart docker
# 查看配置
docker info
Docker 常用命令
1)Docker 進程相關命令
Docker 信息相關命令:
# Docker 版本信息
docker version
# Docker 系統信息
docker info
Docker 啟停相關命令:
# 啟動 Docker 服務
systemctl start docker
# 停止 Docker 服務
systemctl stop docker
# 重啟 Docker 服務
systemctl restart docker
# 查看 Docker 服務狀態
systemctl status docker
# 設置開機啟動 Docker 服務
systemctl enable docker
2)Docker 鏡像相關命令
docker search:查找鏡像倉庫中的鏡像
# 比如想要搜索具有 nginx 功能的容器
docker search nginx
- 第一列鏡像名稱,如果沒有路徑符號”/”,說明在默認路徑中,如果有路徑,說明在子倉庫中。
- 第二列描述,簡要說明該鏡像的用途和特點。如果想要完整顯示說明,可以增加參數 --no-trunc。
- 第三列是點贊數,類似於 git 上的點贊。
- 第四列標明是否為官方發布。
- 第五列是自動構建,是用 webhook 探測源碼的變化,一旦有變化就自動生成新的版本鏡像。
docker pull:下載鏡像
從 Docker 倉庫下載鏡像到本地,鏡像名稱格式為名稱:版本號
,如果版本號不指定則是最新的版本。
docker pull nginx
如下圖所示,將會下載該鏡像。注意看該鏡像會有多個分層,之后再下載其它鏡像的時候,有可能部分層級可以復用,不需要全部下載。
另外注意箭頭指的位置,由於 docker pull nginx 沒有指定 tag(版本),會使用默認的版本下載。
再嘗試下載 alpine 環境,alpine 是一款輕量級操作系統,只有 5M 左右。很多鏡像制作都會選擇 alpine 作為基礎鏡像。這里僅下載一個純凈的 alpine,作為后續演示使用。
docker pull alpine
注意查看下圖中,docker pull 命令后面的 nginx 跟了 tag,可以看出,tag 不僅僅包含了版本號,還包含了主要的特性。
另外看箭頭所指,之前下載過 alpine 的基本鏡像,所以基於 alpine 的 nginx 會省略下載 alpine,復用之前下載的已存在分層。
docker inspect:查看鏡像/容器的詳細信息
docker inspect 鏡像/容器名稱
在 hub.docker.com 上查找鏡像
也可以在 hub.docker.com 網站上查找鏡像,同時還可以看到該鏡像的 tag 信息,選擇合適的 tag 下載。
如上述步驟,找到其它版本的 tag,可以點擊這個復制按鈕,直接將命令復制出來。
docker images:查看本地鏡像
docker images # 查看本地所有的鏡像
docker images –q # 僅顯示鏡像id,常用於批量刪除鏡像
docker rmi:刪除本地鏡像
docker rmi 鏡像id或鏡像名稱的前綴即可 # 刪除指定的本地鏡像
docker rmi `docker images -q` # 刪除所有本地鏡像
本地鏡像或者遠程鏡像倉庫中的垃圾鏡像越來越多時,需要進行清理刪除。
圖中存在沒有 repository 和 tag 的鏡像的原因是:使用相同的鏡像名稱構建新鏡像時,由於 dockerfile 中的基礎鏡像或者 RUN 后面的命令有變化,就會導致舊的重名鏡像變成沒有 repository 和 tag 的情況。
docker history:查看鏡像構建歷史
docker history [options] IMAGE
通常只用一個參數 --no-trunc:不截斷輸出。
docker history 命令在查看自己構建的鏡像時會相對容易和方便一些。官方鏡像總要考慮大部分的需求,所以相對比較繁瑣。
docker save:導出鏡像
docker save 鏡像名稱 > 鏡像名稱.tar
docker load:導入鏡像
docker load < 鏡像名稱.tar
鏡像重命名
docker tag 鏡像原來名稱 鏡像新名稱
3)Docker 容器相關命令
-
容器的本質是管理進程。啟動容器必定會伴隨容器內一個或者多個用戶進程的啟動,
如果容器內的用戶進程在啟動后執行完畢或者崩潰,那么該容器就會退出
。與虛擬機不同,虛擬機啟動的是操作系統,如果沒有用戶進程,則會等待用戶的登錄和操作。 -
最好是一個容器只執行一個進程,完成單一任務。
-
雖然容器可以被登錄,但最好不要登錄進去操作,除非是為了修改鏡像。
docker run:啟動容器
docker run 參數
# -it 創建的容器一般稱為交互式容器
# -id 創建的容器一般稱為守護式容器
參數說明:
- -i:保持容器運行
- 通常與 -t 同時使用。加入 it 這兩個參數后,容器創建后會自動進入容器中。
- 退出容器后,容器自動關閉。
- -t:為容器重新分配一個偽輸入終端
- 通常與 -i 同時使用。
- -d:以守護(后台)模式運行容器
- 創建一個容器並在后台運行,需要使用 docker exec 進入容器。
- 退出容器后,容器不會關閉。
- --name:為創建的容器命名。
示例:docker run -it alpine
如圖所示已經進入了容器的 shell,可以操作查看這個 shell:
- uname -a 查到系統內核和宿主機的一致,說明容器使用底層宿主機的內核。
- pwd 和 ls 可以看到此時 shell 的目錄結構和宿主機不一致。
容器是用來管理進程的,在虛擬機的宿主機中,執行 ps 是看不到虛擬機內部的進程的。但是容器不一樣,在容器的宿主機中執行 ps,是可以看到容器執行的進程的。從本質上看,容器僅僅是在宿主機中把進程啟動起來,並且進行資源隔離。
容器退出
-
使用 ctrl+d 或 exit 命令,容器都會退出。ctrl+d 或者 exit 相當於結束當前 shell,在未指定命令情況下啟動容器時,相當於僅啟動了 /bin/bash,退出后結束 bash,容器退出。
-
使用 ctrl+q+p 退出,會保持該容器在后台運行,容器不會結束。
docker ps:查看當前容器狀態
docker ps # 查看正在運行的容器
docker ps –a # 查看所有容器
docker ps –qa # 僅顯示 id 號,常用於批量刪除容器
如上圖所示,不加任何參數,查看正在運行的容器:目前沒有正在運行的容器。
- CONTAINER ID:容器的 ID。
- IMAGE:啟動使用的鏡像。
- COMMAND:啟動容器時傳入的命令。
- CREATED:創建時間。
- STATUS:容器狀態。
- PORTS:端口映射情況。
- NAMES:容器的名稱,如果沒有指定,會隨機分配。
-a 參數可以查看所有狀態的容器,包括停止、退出等狀態的容器。
如上圖所示目前有一個容器,但狀態是已經退出。
docker pause:暫停容器
docker pause CONTAINER [CONTAINER] # 暫停
docker unpause CONTAINER [CONTAINER] # 恢復
如圖所示,docker pause 時用的容器 mynginx 進入了暫停狀態。恢復的時候用的容器 id,容器恢復正常狀態。注意恢復后的狀態開啟時間並沒有重新計時,而是繼續計時,暫停時間也會算進開機時間。
如果使用容器 id 則只要用 id 的前若干位即可,只要前幾位沒有沖突,通常使用三位。這個規則適用於整個 docker 的場景。
Paused 狀態意味着暫停、掛起,但是容器管理的進程並沒有停止。整體上更像是虛擬機的快照暫停方式,把當前容器做個快照放在磁盤中,然后釋放該容器的資源。等需要恢復的時候,把容器的內容從磁盤中讀出來重新進入內存。底層使用的是 cgroup 的 freezer 能力。
docker stop:停止容器
docker stop CONTAINER [CONTAINER] # 停止
docker start CONTAINER [CONTAINER] # 啟動
docker restart CONTAINER [CONTAINER] # 重啟
這三個狀態類比虛擬機,就是關機、啟動和重啟。stop 后容器管理的進程會徹底停止、清理內存;start 啟動容器時會沿用容器 run 或者 create 時候的參數。
這和虛擬機類似的操作過程相同,磁盤中的內容會被保存,但是內存中的內容會被清理掉。
docker exec:進入容器
對於后台執行的容器或者容器的輸出日志,我們都有查看的需求。
方式一:docker attach(不推薦使用)
該命令使用不當的話,會導致容器中的進程結束運行,進而容器退出。使用的時候一定加上 --sig-proxy=false 參數。
方式二:docker exec(推薦使用)
docker exec [options] CONTAINER CMD
該命令用途是在運行中的容器里執行命令,當然也可以在運行的容器中執行 /bin/bash。
注意 exec 不默認傳參數,必須跟參數:
上圖中,首先在后台啟動一個交互式 alpine 容器,並查看這個容器狀態,確認運行中。后續操作需要用到容器名稱,所以重命名一下。接着讓這個容器執行一下 echo 命令。可以看到執行后容器輸出 hello,並且不會退出,仍然在運行狀態中。
執行 /bin/bash,就可以進到容器中進行操作,注意 /bin/bash 需要交互和打開標准輸入:
如上圖中的報錯,最初執行 docker exec -it myalpine /bin/bash,由於 alpine 中沒有 bash 這個命令,所以報錯。
使用 /bin/sh 后就可以進入容器執行命令了,退出后不影響原容器運行。
注意很多鏡像里面並不帶 kill 命令,但是如果帶 kill 命令並且在 exec 中執行 kill 主進程操作,或者執行了主進程的停止操作,會導致容器直接退出。
docker create:創建容器
docker create [option] IMAGE [CMD]
docker run 命令相當於執行了 create 和 start 兩個命令。
docker rename:容器重命名
docker rename 容器原來名稱 容器新名稱
docker log:查看容器日志
docker logs [options] CONTAINER
docker rm:刪除容器
不加 -f 參數時,如果容器是運行狀態則刪除失敗,需要停止容器才能刪除。
docker rm [OPTIONS] 容器名稱/id [CONTAINER...]
OPTIONS 說明:
- 不加參數情況下,可以刪除已經停止的容器。
- -f:通過 SIGKILL 信號刪除一個正在運行的容器。
- -l:移除容器間的網絡,而非容器本身。
- -v:刪除與容器映射的目錄。
宿主機運行一段時間后,會有大量已經停止的容器,如果需要批量刪除,可以使用以下命令:
docker rm $(docker ps -qa)
最終只剩下運行中的容器。當然也可以使用 -f 參數刪除所有容器,慎重使用。
docker commit:生成鏡像
若以交互模式修改了容器內容,需要 commit 成新的鏡像。
1)修改容器內容:
[root@MiWiFi-R3P-srv tmp]# docker run -it centos
[root@e59e110aaf47 /]# yum install -y nginx
[root@e59e110aaf47 /]# vi /etc/nginx/nginx.conf # 在全局配置中加入"daemon off;"
2)退出容器:
3)執行 commit 命令:
4)運行中的容器也可以 commit,並且容器層的數據也會保留:
- 注意上圖中,啟動 nginx:v7commit 需要以 nginx 的啟動命令,否則容器會退出;
- 使用 docker exec 進入容器,並編輯內容;
- 本次 commit 使用和之前完全一樣的鏡像名稱和 tag,所以在名稱前加一個 test 目錄;
- 接下來啟動這個鏡像,看 echo 修改的內容和文件會不會存在:
docker top:查看容器中運⾏的進程
docker top 容器名稱
docker stats:查看資源占⽤
docker stats 容器名稱
docker cp:拷貝宿主機/容器中的文件
該命令和存儲無關,但是可以把容器內的文件拷貝出來,或者把宿主機文件拷貝進容器。
docker cp CONTAINER:dir host_dir
docker cp host_dir CONTAIN:dir
整體寫法和 cp 一樣,只是要加上容器的 id 號或者名字。
如下示例,將容器中整個目錄拷貝出來,注意不需要加 -r 參數:
--restart:開機自啟動
在運行 docker 容器時可以加如下參數,來保證每次 docker 服務重啟后,容器會自動啟動。
docker run --restart=always CONTAINER_ID
如果已經啟動了則可以使用如下命令:
docker update --restart=always CONTAINER_ID # 自動啟動
docker update --restart=no CONTAINER_ID # 不自動啟動
Docker 容器的數據卷(Volumn)
什么是數據卷?
問題現象:
- Docker 容器刪除后,在容器中產生的數據也會隨之銷毀。
- Docker 容器和外部機器可以直接交換文件嗎?不能。
- 容器之間想要進行數據交互?
上述問題的解決方案:數據卷
什么是數據卷?
- 數據卷是宿主機中的一個目錄或文件。
- 當容器目錄和數據卷目錄綁定后,對方的修改會立即同步。
- 一個數據卷可以被多個容器同時掛載。
- 一個容器也可以被掛載多個數據卷。
數據卷的作用:
- 容器數據持久化。
- 容器和外部機器間接通信。
- 容器之間數據交換。
配置數據卷
創建啟動容器時,使用 –v 參數設置數據卷:
docker run ... –v 宿主機目錄(文件):容器內目錄(文件) ...
注意:
- (兩邊)目錄必須是絕對路徑
- 如果(兩邊)目錄不存在,會自動創建
數據卷容器
多容器進行數據交換:
- c1 和 c2 容器可以同時通過宿主機和 c3(數據卷容器)掛載數據卷。
- 即使 c3 掛了,也不影響 c1 和 c2 與宿主機同步數據。
配置方法:創建一個容器,掛載一個目錄,讓其他容器繼承自該容器(--volume-from)
# 創建啟動 c3 數據卷容器,使用 –v 參數設置數據卷
docker run –it --name=c3 –v /volume centos:7 /bin/bash # 注意這里只需要容器目錄即可,宿主機會隨機分配掛載目錄
# 創建啟動 c1 c2 容器,使用 –-volumes-from 參數設置數據卷
docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bash
docker run –it --name=c2 --volumes-from c3 centos:7 /bin/bash
Docker 應用部署
端口映射問題
如果外部機器要訪問到容器中的應用,首先需要解決端口映射問題(容器需要映射端口才能和外部通信)。提到端口映射,就涉及到容器的網絡和主機網絡之間的關系。
- 容器內的網絡服務和外部機器不能直接通信
- 外部機器和宿主機可以直接通信
- 宿主機和容器可以直接通信
- 因此,當容器中的網絡服務需要被外部機器訪問時,可以
將容器中提供服務的端口映射到宿主機的端口上,外部機器訪問宿主機的該端口,從而間接訪問容器的服務
。這種操作稱為:端口映射
防火牆配置
示例:Centos 8 使用 firewalld 服務管理轉發規則。firewalld 服務必須打開,不然 docker 無法創建端口轉發,但是打開后會攔截 80、8080 和 32000 以上的端口,導致 web 端口全都無法通過,所以需要用 firewalld 打開端口限制。
# 打開防火牆
systemctl start firewalld.service
# 防火牆開機啟動
systemctl enable firewalld.service
# 將主機網卡加入信任域
firewall-cmd --permanent --zone=trusted --change-interface=enp0s3
# 增加80口信任
firewall-cmd --add-port=80/tcp --permanent
# 增加 8080 端口信任
firewall-cmd --add-port=8080/tcp --permanent
# 增加 32001--65010 口信任
firewall-cmd --add-port=32001-65010/tcp --permanent
# 重新加載配置文件
firewall-cmd --reload
端口映射配置
端口映射在 docker run 或 create 時配置,參數使用 -P(隨機映射)或 -p(指定映射)。
隨機映射:-P
docker 會給宿主機上所有 IP(0.0.0.0)分配一個 32000 以上的隨機端口,映射到容器內對外提供服務的端口。
如上圖所示,使用 docker ps,可以看到宿主機 32769 端口映射到容器 80 端口。
再查看宿主機 IP,用此 IP 加 32769 端口訪問 nginx 的默認頁面(注意宿主機的防火牆需要關閉或者設置):
可以看到通過宿主機 IP 加上隨機分配的端口,就可以訪問容器提供的 web 服務。
隨即映射:-P
注意事項:
- 選擇指定端口進行映射時,宿主機端口不能被占用。
- 如果容器啟動時綁定的僅是宿主機 IP,則宿主機本機訪問 127.0.0.1 的 80 端口是不通的(ps 中 0.0.0.0:80 才代表所有 IP 均被綁定)。
部署 MySQL
- 搜索 mysql 鏡像:
docker search mysql
- 拉取 mysql 鏡像:
docker pull mysql:5.6
- 創建容器,設置端口映射、目錄映射:
# 在/root目錄下創建mysql目錄用於存儲mysql數據信息
mkdir ~/mysql
cd ~/mysql
-
從 docker hub 上可以找到 mysql 外掛配置和數據目錄的一些文檔說明:https://hub.docker.com/_/mysql
-
從該文檔中可以了解到,mysql 的默認配置為 /etc/mysql/my.cnf,該文件中包含了一個額外的數據目錄 /etc/mysql/conf.d 或者 /etc/mysql/mysql.conf.d
docker run -id \
-p 3307:3306 \
--name=c_mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
--privileged=true \
-u root \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.6
- 參數說明:
- -p 3307:3306:將容器的 3306 端口映射到宿主機的 3307 端口
- -v $PWD/conf:/etc/mysql/conf.d:將主機當前目錄下的 conf/my.cnf 目錄掛載到容器的 /etc/mysql/my.cnf 目錄
- -v $PWD/logs:/logs:將主機當前目錄下的 logs 目錄掛載到容器的 /logs
- -v $PWD/data:/var/lib/mysql :將主機當前目錄下的 data 目錄掛載到容器的 /var/lib/mysql
- --privileged=true:使得容器內的 root 擁有真正的 root 權限,否則容器內的 root 只是外部的一個普通用戶權限
- -u root:以 root 用戶登錄數據庫
- -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用戶的密碼
- 進入容器,操作 mysql :
docker exec –it c_mysql /bin/bash
- 使用外部機器連接容器中的 mysql :
部署 Tomcat
- 搜索 tomcat 鏡像:
docker search tomcat
- 拉取 tomcat 鏡像:
docker pull tomcat
- 創建容器,設置端口映射、目錄映射:
# 在 /root 目錄下創建 tomcat 目錄用於存儲 tomcat 數據信息
mkdir ~/tomcat
cd ~/tomcat
docker run -id --name=c_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
-
參數說明:
-
-p 8080:8080:將容器的 8080 端口映射到主機的 8080 端口
-v $PWD:/usr/local/tomcat/webapps:將主機中當前目錄掛載到容器的 webapps
-
- 在宿主機掛載目錄下創建訪問文件,並使用外部機器訪問 tomcat 中的該文件:
部署 Redis
- 搜索 redis 鏡像:
docker search redis
- 拉取 redis 鏡像:
docker pull redis:5.0
- 創建容器,設置端口映射:
docker run -id --name=c_redis -p 6379:6379 redis:5.0
- 使用外部機器連接 redis :
./redis-cli.exe -h 192.168.149.135 -p 6379