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://registry.docker-cn.com"]
}
# 過載 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:刪除容器
如果容器是執行狀態則刪除失敗,需要停止容器才能刪除。
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 容器的資料卷(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 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 \
-e MYSQL_ROOT_PASSWORD=123456 \
- 引數說明:
- -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
- -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 :
部署 Nginx
- 搜尋 nginx 映象:
docker search nginx
- 拉取 nginx 映象:
docker pull nginx
- 建立容器,設定埠對映、目錄對映:
# 在 /root 目錄下建立 nginx 目錄用於儲存 nginx 資料資訊
mkdir ~/nginx
cd ~/nginx
mkdir conf
cd conf
# 在 ~/nginx/conf/ 下建立 nginx.conf 檔案,貼上以下內容
vi nginx.conf
- nginx.conf 配置:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
- 建立容器:
docker run -id --name=c_nginx \
-p 80:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
- 引數說明:
- -p 80:80:將容器的 80 埠對映到宿主機的 80 埠
- -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:將主機當前目錄下的 /conf/nginx.conf 掛載到容器的 /etc/nginx/nginx.conf
- -v $PWD/logs:/var/log/nginx:將主機當前目錄下的 logs 目錄掛載到容器的/var/log/nginx
- 使用外部機器訪問 nginx :
部署 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