目錄
一、Docker簡介
二、安裝Docker
2.1、卸載舊版
2.2、配置Docker的yum庫
2.3、安裝Docker
2.4、啟動和校驗
2.5、配置鏡像加速
2.5.1、注冊阿里云賬號
2.5.2、開通鏡像服務
2.5.3、配置鏡像加速
三、快速入門
3.1、部署MYSQL
3.2、命令解讀
四、Docker基礎
4.1、常見命令
4.1.1、命令介紹
4.1.2、案例演示
4.1.3、命名別名
4.2、數(shù)據(jù)卷
4.2.1、什么是數(shù)據(jù)卷?
4.2.2、數(shù)據(jù)卷命令
4.2.3、掛載本地目錄或文件
4.3、鏡像
4.3.1、鏡像結(jié)構(gòu)
4.3.2、Dockerfile
4.3.3、構(gòu)建鏡像
4.4、網(wǎng)絡
五、項目部署
5.1、部署Java(SpringBoot)項目
5.2、部署前端
5.3、DockerCompose
5.3.1、基本語法
5.3.2、基本命令
一、Docker簡介
我們先知道Docker能為我們解決什么樣的問題?
比如我們Linux上部署MYSQL,很多很多步驟,而且可能安到最后,還會報錯,簡直是絕望??!
但如果我們使用Docker來安裝MYSQL,只需要這一條命令,就可以順利安裝,簡單吧!
二、安裝Docker
2.1、卸載舊版
首先如果系統(tǒng)中已經(jīng)存在舊的Docker,則先卸載:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2.2、配置Docker的yum庫
首先要安裝一個yum工具
yum install -y yum-utils
安裝成功后,執(zhí)行命令,配置Docker的yum源:
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
2.3、安裝Docker
最后,執(zhí)行命令,安裝Docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
2.4、啟動和校驗
# 啟動Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重啟
systemctl restart docker
# 設置開機自啟
systemctl enable docker
# 執(zhí)行docker ps命令,如果不報錯,說明安裝啟動成功
docker ps
2.5、配置鏡像加速
這里以阿里云加速為例。
2.5.1、注冊阿里云賬號
首先訪問阿里云網(wǎng)站:
阿里云-計算,為了無法計算的價值
注冊一個賬號。
2.5.2、開通鏡像服務
在首頁的產(chǎn)品中,找到阿里云的容器鏡像服務:
點擊后進入控制臺:
首次可能需要選擇立刻開通,然后進入控制臺。
2.5.3、配置鏡像加速
找到鏡像工具下的鏡像加速器:
頁面向下滾動,即可找到配置的文檔說明:
具體命令如下:
# 創(chuàng)建目錄
mkdir -p /etc/docker
# 復制內(nèi)容,注意把其中的鏡像加速地址改成你自己的
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
EOF
# 重新加載配置
systemctl daemon-reload
# 重啟Docker
systemctl restart docker
直接全粘貼,運行即可。
三、快速入門
3.1、部署MYSQL
先停掉虛擬機中的MySQL,確保你的虛擬機已經(jīng)安裝Docker,且網(wǎng)絡開通的情況下,執(zhí)行下面命令即可安裝MySQL:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
運行效果如圖:
MySQL安裝完畢!通過任意客戶端工具即可連接到MySQL.
大家可以發(fā)現(xiàn),當我們執(zhí)行命令后,Docker做的第一件事情,是去自動搜索并下載了MySQL,然后會自動運行MySQL,我們完全不用插手,是不是非常方便。
而且,這種安裝方式你完全不用考慮運行的操作系統(tǒng)環(huán)境,它不僅僅在CentOS系統(tǒng)是這樣,在Ubuntu系統(tǒng)、macOS系統(tǒng)、甚至是裝了WSL的Windows下,都可以使用這條命令來安裝MySQL。
要知道,不同操作系統(tǒng)下其安裝包、運行環(huán)境是都不相同的!如果是手動安裝,必須手動解決安裝包不同、環(huán)境不同的、配置不同的問題!
而使用Docker,這些完全不用考慮。就是因為Docker會自動搜索并下載MySQL。注意:這里下載的不是安裝包,而是鏡像。鏡像中不僅包含了MySQL本身,還包含了其運行所需要的環(huán)境、配置、系統(tǒng)級函數(shù)庫。因此它在運行時就有自己獨立的環(huán)境,就可以跨系統(tǒng)運行,也不需要手動再次配置環(huán)境了。這套獨立運行的隔離環(huán)境我們稱為容器。
說明:
-
鏡像:英文是image
-
容器:英文是container
因此,Docker安裝軟件的過程,就是自動搜索下載鏡像,然后創(chuàng)建并運行容器的過程。
Docker會根據(jù)命令中的鏡像名稱自動搜索并下載鏡像,那么問題來了,它是去哪里搜索和下載鏡像的呢?這些鏡像又是誰制作的呢?
Docker官方提供了一個專門管理、存儲鏡像的網(wǎng)站,并對外開放了鏡像上傳、下載的權利。Docker官方提供了一些基礎鏡像,然后各大軟件公司又在基礎鏡像基礎上,制作了自家軟件的鏡像,全部都存放在這個網(wǎng)站。這個網(wǎng)站就成了Docker鏡像交流的社區(qū)。
https://hub.docker.com
基本上我們常用的各種軟件都能在這個網(wǎng)站上找到,我們甚至可以自己制作鏡像上傳上去。
像這種提供存儲、管理Docker鏡像的服務器,被稱為DockerRegistry,可以翻譯為鏡像倉庫。DockerHub網(wǎng)站是官方倉庫,阿里云、華為云會提供一些第三方倉庫,我們也可以自己搭建私有的鏡像倉庫。
官方倉庫在國外,下載速度較慢,一般我們都會使用第三方倉庫提供的鏡像加速功能,提高下載速度。而企業(yè)內(nèi)部的機密項目,往往會采用私有鏡像倉庫。
3.2、命令解讀
利用Docker快速的安裝了MySQL,非常的方便,不過我們執(zhí)行的命令到底是什么意思呢?
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
解讀:
-
docker run -d
:創(chuàng)建并運行一個容器,-d
則是讓容器以后臺進程運行 -
--name mysql
: 給容器起個名字叫mysql
,你可以叫別的 -
-p 3306:3306
: 設置端口映射。-
容器是隔離環(huán)境,外界不可訪問。但是可以將宿主機端口映射容器內(nèi)到端口,當訪問宿主機指定端口時,就是在訪問容器內(nèi)的端口了。
-
容器內(nèi)端口往往是由容器內(nèi)的進程決定,例如MySQL進程默認端口是3306,因此容器內(nèi)端口一定是3306;而宿主機端口則可以任意指定,一般與容器內(nèi)保持一致。
-
格式:
-p 宿主機端口:容器內(nèi)端口
,示例中就是將宿主機的3306映射到容器內(nèi)的3306端口
-
-
-e TZ=Asia/Shanghai
: 配置容器內(nèi)進程運行時的一些參數(shù)-
格式:
-e KEY=VALUE
,KEY和VALUE都由容器內(nèi)進程決定 -
案例中,
TZ=Asia/Shanghai
是設置時區(qū);MYSQL_ROOT_PASSWORD=123
是設置MySQL默認密碼
-
-
mysql
: 設置鏡像名稱,Docker會根據(jù)這個名字搜索并下載鏡像-
格式:
REPOSITORY:TAG
,例如mysql:8.0
,其中REPOSITORY
可以理解為鏡像名,TAG
是版本號 -
在未指定
TAG
的情況下,默認是最新版本,也就是mysql:latest
-
四、Docker基礎
4.1、常見命令
4.1.1、命令介紹
命令 |
說明 |
文檔地址 |
---|---|---|
docker pull |
拉取鏡像 |
docker pull |
docker push |
推送鏡像到DockerRegistry |
docker push |
docker images |
查看本地鏡像 |
docker images |
docker rmi |
刪除本地鏡像 |
docker rmi |
docker run |
創(chuàng)建并運行容器(不能重復創(chuàng)建) |
docker run |
docker stop |
停止指定容器 |
docker stop |
docker start |
啟動指定容器 |
docker start |
docker restart |
重新啟動容器 |
docker restart |
docker rm |
刪除指定容器 |
docs.docker.com |
docker ps |
查看容器 |
docker ps |
docker logs |
查看容器運行日志 |
docker logs |
docker exec |
進入容器 |
docker exec |
docker save |
保存鏡像到本地壓縮文件 |
docker save |
docker load |
加載本地壓縮文件到鏡像 |
docker load |
docker inspect |
查看容器詳細信息 |
docker inspect |
補充:
默認情況下,每次重啟虛擬機我們都需要手動啟動Docker和Docker中的容器。通過命令可以實現(xiàn)開機自啟:
# Docker開機自啟
systemctl enable docker
# Docker容器開機自啟
docker update --restart=always [容器名/容器id]
4.1.2、案例演示
用Nginx為例,我們走一遍流程。
# 第1步,去DockerHub查看nginx鏡像倉庫及相關信息
# 第2步,拉取Nginx鏡像
docker pull nginx
# 第3步,查看鏡像
docker images
# 結(jié)果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB
# 第4步,創(chuàng)建并允許Nginx容器
docker run -d --name nginx -p 80:80 nginx
# 第5步,查看運行中容器
docker ps
# 也可以加格式化方式訪問,格式會更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第6步,訪問網(wǎng)頁,地址:http://虛擬機地址
# 第7步,停止容器
docker stop nginx
# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第9步,再次啟動nginx容器
docker start nginx
# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第11步,查看容器詳細信息
docker inspect nginx
# 第12步,進入容器,查看容器內(nèi)目錄
docker exec -it nginx bash
# 或者,可以進入MySQL
docker exec -it mysql mysql -uroot -p
# 第13步,刪除容器
docker rm nginx
# 發(fā)現(xiàn)無法刪除,因為容器運行中,強制刪除容器
docker rm -f nginx
4.1.3、命名別名
給常用Docker命令起別名,方便我們訪問:
# 修改/root/.bashrc文件
vi /root/.bashrc
內(nèi)容如下:
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
然后,執(zhí)行命令使別名生效:
source /root/.bashrc
4.2、數(shù)據(jù)卷
容器是隔離環(huán)境,容器內(nèi)程序的文件、配置、運行時產(chǎn)生的容器都在容器內(nèi)部,我們要讀寫容器內(nèi)的文件非常不方便。大家思考幾個問題:
-
如果要升級MySQL版本,需要銷毀舊容器,那么數(shù)據(jù)豈不是跟著被銷毀了?
-
MySQL、Nginx容器運行后,如果我要修改其中的某些配置該怎么辦?
-
我想要讓Nginx代理我的靜態(tài)資源怎么辦?
因此,容器提供程序的運行環(huán)境,但是程序運行產(chǎn)生的數(shù)據(jù)、程序運行依賴的配置都應該與容器解耦。
你像我們創(chuàng)建一個Nginx容器,我們想用vi命令改一下某個文件,卻發(fā)現(xiàn)容器里根本沒有vi命令,因為容器給我們的運行環(huán)境肯定是最小的,所以這個時候數(shù)據(jù)卷的用處就大了。
4.2.1、什么是數(shù)據(jù)卷?
數(shù)據(jù)卷(volume)是一個虛擬目錄,是容器內(nèi)目錄與宿主機目錄之間映射的橋梁。
以Nginx為例,我們知道Nginx中有兩個關鍵的目錄:
-
html
:放置一些靜態(tài)資源 -
conf
:放置配置文件
如果我們要讓Nginx代理我們的靜態(tài)資源,最好是放到html
目錄;如果我們要修改Nginx的配置,最好是找到conf
下的nginx.conf
文件。
但遺憾的是,容器運行的Nginx所有的文件都在容器內(nèi)部。所以我們必須利用數(shù)據(jù)卷將兩個目錄與宿主機目錄關聯(lián),方便我們操作。如圖:
在上圖中:
-
我們創(chuàng)建了兩個數(shù)據(jù)卷:
conf
、html
-
Nginx容器內(nèi)部的
conf
目錄和html
目錄分別與兩個數(shù)據(jù)卷關聯(lián)。 -
而數(shù)據(jù)卷conf和html分別指向了宿主機的
/var/lib/docker/volumes/conf/_data
目錄和/var/lib/docker/volumes/html/_data
目錄
這樣以來,容器內(nèi)的conf
和html
目錄就與宿主機的conf
和html
目錄關聯(lián)起來,我們稱為掛載。此時,我們操作宿主機的/var/lib/docker/volumes/html/_data
就是在操作容器內(nèi)的/usr/share/nginx/html/_data
目錄。只要我們將靜態(tài)資源放入宿主機對應目錄,就可以被Nginx代理了。
記住,是雙向綁定的哦?。。?/strong>
問題1:/var/lib/docker/volumes
這個目錄就是默認的存放所有容器數(shù)據(jù)卷的目錄,其下再根據(jù)數(shù)據(jù)卷名稱創(chuàng)建新目錄,格式為/數(shù)據(jù)卷名/_data
。
問題2:為什么不讓容器目錄直接指向宿主機目錄呢?
-
因為直接指向宿主機目錄就與宿主機強耦合了,如果切換了環(huán)境,宿主機目錄就可能發(fā)生改變了。由于容器一旦創(chuàng)建,目錄掛載就無法修改,這樣容器就無法正常工作了。
-
但是容器指向數(shù)據(jù)卷,一個邏輯名稱,而數(shù)據(jù)卷再指向宿主機目錄,就不存在強耦合。如果宿主機目錄發(fā)生改變,只要改變數(shù)據(jù)卷與宿主機目錄之間的映射關系即可。
4.2.2、數(shù)據(jù)卷命令
命令 |
說明 |
文檔地址 |
---|---|---|
docker volume create |
創(chuàng)建數(shù)據(jù)卷 |
docker volume create |
docker volume ls |
查看所有數(shù)據(jù)卷 |
docs.docker.com |
docker volume rm |
刪除指定數(shù)據(jù)卷 |
docs.docker.com |
docker volume inspect |
查看某個數(shù)據(jù)卷的詳情 |
docs.docker.com |
docker volume prune |
清除數(shù)據(jù)卷 |
docker volume prune |
注意:容器與數(shù)據(jù)卷的掛載要在創(chuàng)建容器時配置,對于創(chuàng)建好的容器,是不能設置數(shù)據(jù)卷的。而且創(chuàng)建容器的過程中,數(shù)據(jù)卷會自動創(chuàng)建。
教學演示環(huán)節(jié):演示一下nginx的html目錄掛載:
# 1.首先創(chuàng)建容器并指定數(shù)據(jù)卷,注意通過 -v 參數(shù)來指定數(shù)據(jù)卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
# 2.然后查看數(shù)據(jù)卷
docker volume ls
# 結(jié)果
DRIVER VOLUME NAME
local 29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
local html
# 3.查看數(shù)據(jù)卷詳情
docker volume inspect html
# 結(jié)果
[
{
"CreatedAt": "2024-05-17T19:57:08+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
# 4.查看/var/lib/docker/volumes/html/_data目錄
ll /var/lib/docker/volumes/html/_data
# 可以看到與nginx的html目錄內(nèi)容一樣,結(jié)果如下:
總用量 8
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html
# 5.進入該目錄,并隨意修改index.html內(nèi)容
cd /var/lib/docker/volumes/html/_data
vi index.html
# 6.打開頁面,查看效果
# 7.進入容器內(nèi)部,查看/usr/share/nginx/html目錄內(nèi)的文件是否變化
docker exec -it nginx bash
注意:你像我們這個例子是指定了掛載目錄,如果不指定,自動會為你掛載到/usr/lib下。
4.2.3、掛載本地目錄或文件
可以發(fā)現(xiàn),數(shù)據(jù)卷的目錄結(jié)構(gòu)較深,如果我們?nèi)ゲ僮鲾?shù)據(jù)卷目錄會不太方便。在很多情況下,我們會直接將容器目錄與宿主機指定目錄掛載。掛載語法與數(shù)據(jù)卷類似:
# 掛載本地目錄
-v 本地目錄:容器內(nèi)目錄
# 掛載本地文件
-v 本地文件:容器內(nèi)文件
注意:本地目錄或文件必須以 /
或 ./
開頭,如果直接以名字開頭,會被識別為數(shù)據(jù)卷名而非本地目錄名。
例如:
-v mysql:/var/lib/mysql # 會被識別為一個數(shù)據(jù)卷叫mysql,運行時會自動創(chuàng)建這個數(shù)據(jù)卷
-v ./mysql:/var/lib/mysql # 會被識別為當前目錄下的mysql目錄,運行時如果不存在會創(chuàng)建目錄
教學演示:刪除并重新創(chuàng)建mysql容器,并完成本地目錄掛載:
-
掛載
/root/mysql/data
到容器內(nèi)的/var/lib/mysql
目錄 -
掛載
/root/mysql/init
到容器內(nèi)的/docker-entrypoint-initdb.d
目錄(初始化的SQL腳本目錄) -
掛載
/root/mysql/conf
到容器內(nèi)的/etc/mysql/conf.d
目錄(這個是MySQL配置文件目錄)
在課前資料中已經(jīng)準備好了mysql的init
目錄和conf
目錄:
以及對應的初始化SQL腳本和配置文件:
其中,hm.cnf主要是配置了MySQL的默認編碼,改為utf8mb4;而hmall.sql則是后面我們要用到的黑馬商城項目的初始化SQL腳本。
我們直接將整個mysql目錄上傳至虛擬機的/root
目錄下:
接下來,我們演示本地目錄掛載:
# 1.刪除原來的MySQL容器
docker rm -f mysql
# 2.進入root目錄
cd ~
# 3.創(chuàng)建并運行新mysql容器,掛載本地目錄
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
mysql
# 4.查看root目錄,可以發(fā)現(xiàn)~/mysql/data目錄已經(jīng)自動創(chuàng)建好了
ls -l mysql
# 結(jié)果:
總用量 4
drwxr-xr-x. 2 root root 20 5月 19 15:11 conf
drwxr-xr-x. 7 polkitd root 4096 5月 19 15:11 data
drwxr-xr-x. 2 root root 23 5月 19 15:11 init
# 查看data目錄,會發(fā)現(xiàn)里面有大量數(shù)據(jù)庫數(shù)據(jù),說明數(shù)據(jù)庫完成了初始化
ls -l data
# 5.查看MySQL容器內(nèi)數(shù)據(jù)
# 5.1.進入MySQL
docker exec -it mysql mysql -uroot -p123
# 5.2.查看編碼表
show variables like "%char%";
# 5.3.結(jié)果,發(fā)現(xiàn)編碼是utf8mb4沒有問題
+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
# 6.查看數(shù)據(jù)
# 6.1.查看數(shù)據(jù)庫
show databases;
# 結(jié)果,hmall是黑馬商城數(shù)據(jù)庫
+--------------------+
| Database |
+--------------------+
| hmall |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
# 6.2.切換到hmall數(shù)據(jù)庫
use hmall;
# 6.3.查看表
show tables;
# 結(jié)果:
+-----------------+
| Tables_in_hmall |
+-----------------+
| address |
| cart |
| item |
| order |
| order_detail |
| order_logistics |
| pay_order |
| user |
+-----------------+
# 6.4.查看address表數(shù)據(jù)
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| id | user_id | province | city | town | mobile | street | contact | is_default | notes |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| 59 | 1 | 北京 | 北京 | 朝陽區(qū) | 13900112222 | 金燕龍辦公樓 | 李佳誠 | 0 | NULL |
| 60 | 1 | 北京 | 北京 | 朝陽區(qū) | 13700221122 | 修正大廈 | 李佳紅 | 0 | NULL |
| 61 | 1 | 上海 | 上海 | 浦東新區(qū) | 13301212233 | 航頭鎮(zhèn)航頭路 | 李佳星 | 1 | NULL |
| 63 | 1 | 廣東 | 佛山 | 永春 | 13301212233 | 永春武館 | 李曉龍 | 0 | NULL |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
4 rows in set (0.00 sec)
4.3、鏡像
前面我們一直在使用別人準備好的鏡像,那如果我要部署一個Java項目,把它打包為一個鏡像該怎么做呢?
4.3.1、鏡像結(jié)構(gòu)
要想自己構(gòu)建鏡像,必須先了解鏡像的結(jié)構(gòu)。
之前我們說過,鏡像之所以能讓我們快速跨操作系統(tǒng)部署應用而忽略其運行環(huán)境、配置,就是因為鏡像中包含了程序運行需要的系統(tǒng)函數(shù)庫、環(huán)境、配置、依賴。
因此,自定義鏡像本質(zhì)就是依次準備好程序運行的基礎環(huán)境、依賴、應用本身、運行配置等文件,并且打包而成。
舉個例子,我們要從0部署一個Java應用,大概流程是這樣:
-
準備一個linux服務(CentOS或者Ubuntu均可)
-
安裝并配置JDK
-
上傳Jar包
-
運行jar包
那因此,我們打包鏡像也是分成這么幾步:
-
準備Linux運行環(huán)境(java項目并不需要完整的操作系統(tǒng),僅僅是基礎運行環(huán)境即可)
-
安裝并配置JDK
-
拷貝jar包
-
配置啟動腳本
上述步驟中的每一次操作其實都是在生產(chǎn)一些文件(系統(tǒng)運行環(huán)境、函數(shù)庫、配置最終都是磁盤文件),所以鏡像就是一堆文件的集合。
但需要注意的是,鏡像文件不是隨意堆放的,而是按照操作的步驟分層疊加而成,每一層形成的文件都會單獨打包并標記一個唯一id,稱為Layer(層)。這樣,如果我們構(gòu)建時用到的某些層其他人已經(jīng)制作過,就可以直接拷貝使用這些層,而不用重復制作。
例如,第一步中需要的Linux運行環(huán)境,通用性就很強,所以Docker官方就制作了這樣的只包含Linux運行環(huán)境的鏡像。我們在制作java鏡像時,就無需重復制作,直接使用Docker官方提供的CentOS或Ubuntu鏡像作為基礎鏡像。然后再搭建其它層即可,這樣逐層搭建,最終整個Java項目的鏡像結(jié)構(gòu)如圖所示:
4.3.2、Dockerfile
由于制作鏡像的過程中,需要逐層處理和打包,比較復雜,所以Docker就提供了自動打包鏡像的功能。我們只需要將打包的過程,每一層要做的事情用固定的語法寫下來,交給Docker去執(zhí)行即可。
而這種記錄鏡像結(jié)構(gòu)的文件就稱為Dockerfile,其對應的語法可以參考官方文檔:
Dockerfile reference | Docker Docs
其中的語法比較多,比較常用的有:
指令 |
說明 |
示例 |
---|---|---|
FROM |
指定基礎鏡像 |
|
ENV |
設置環(huán)境變量,可在后面指令使用 |
|
COPY |
拷貝本地文件到鏡像的指定目錄 |
|
RUN |
執(zhí)行Linux的shell命令,一般是安裝過程的命令 |
|
EXPOSE |
指定容器運行時監(jiān)聽的端口,是給鏡像使用者看的 |
EXPOSE 8080 |
ENTRYPOINT |
鏡像中應用的啟動命令,容器運行時調(diào)用 |
ENTRYPOINT java -jar xx.jar |
例如,要基于Ubuntu鏡像來構(gòu)建一個Java應用,其Dockerfile內(nèi)容如下:
# 指定基礎鏡像
FROM ubuntu:16.04
# 配置環(huán)境變量,JDK的安裝目錄、容器內(nèi)時區(qū)
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷貝jdk和java項目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 設定時區(qū)
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安裝JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置環(huán)境變量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定項目監(jiān)聽的端口
EXPOSE 8080
# 入口,java項目的啟動命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
同學們思考一下:以后我們會有很多很多java項目需要打包為鏡像,他們都需要Linux系統(tǒng)環(huán)境、JDK環(huán)境這兩層,只有上面的3層不同(因為jar包不同)。如果每次制作java鏡像都重復制作前兩層鏡像,是不是很麻煩。
所以,就有人提供了基礎的系統(tǒng)加JDK環(huán)境,我們在此基礎上制作java鏡像,就可以省去JDK的配置了:
# 基礎鏡像
FROM openjdk:11.0-jre-buster
# 設定時區(qū)
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷貝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
是不是簡單多了。
4.3.3、構(gòu)建鏡像
當Dockerfile文件寫好以后,就可以利用命令來構(gòu)建鏡像了。
在課前資料中,我們準備好了一個demo項目及對應的Dockerfile:
首先,我們將課前資料提供的docker-demo.jar
包以及Dockerfile
拷貝到虛擬機的/root/demo
目錄:
然后,執(zhí)行命令,構(gòu)建鏡像:
# 進入鏡像目錄
cd /root/demo
# 開始構(gòu)建
docker build -t docker-demo:1.0 .
命令說明:
-
docker build
: 就是構(gòu)建一個docker鏡像 -
-t docker-demo:1.0
:-t
參數(shù)是指定鏡像的名稱(repository
和tag
) -
.
: 最后的點是指構(gòu)建時Dockerfile所在路徑,由于我們進入了demo目錄,所以指定的是.
代表當前目錄,也可以直接指定Dockerfile目錄:
# 直接指定Dockerfile目錄
docker build -t docker-demo:1.0 /root/demo
結(jié)果:
查看鏡像列表:
# 查看鏡像列表:
docker images
# 結(jié)果
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-demo 1.0 d6ab0b9e64b9 27 minutes ago 327MB
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB
然后嘗試運行該鏡像:
# 1.創(chuàng)建并運行容器
docker run -d --name dd -p 8090:8090 docker-demo:1.0
# 2.查看容器
dps
# 結(jié)果
CONTAINER ID IMAGE PORTS STATUS NAMES
78a000447b49 docker-demo:1.0 0.0.0.0:8080->8080/tcp, :::8090->8090/tcp Up 2 seconds dd
f63cfead8502 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 2 hours mysql
# 3.訪問
curl localhost:8080/hello/count
# 結(jié)果:
<h5>歡迎訪問黑馬商城, 這是您第1次訪問<h5>
4.4、網(wǎng)絡
上節(jié)課我們創(chuàng)建了一個Java項目的容器,而Java項目往往需要訪問其它各種中間件,例如MySQL、Redis等?,F(xiàn)在,我們的容器之間能否互相訪問呢?我們來測試一下:
首先,我們查看下MySQL容器的詳細信息,重點關注其中的網(wǎng)絡IP地址:
# 1.用基本命令,尋找Networks.bridge.IPAddress屬性
docker inspect mysql
# 也可以使用format過濾結(jié)果
docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql
# 得到IP地址如下:
172.17.0.2
# 2.然后通過命令進入dd容器
docker exec -it dd bash
# 3.在容器內(nèi),通過ping命令測試網(wǎng)絡
ping 172.17.0.2
# 結(jié)果
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.058 ms
發(fā)現(xiàn)可以互聯(lián),沒有問題。
但是,容器的網(wǎng)絡IP其實是一個虛擬的IP,其值并不固定與某一個容器綁定,如果我們在開發(fā)時寫死某個IP,而在部署時很可能MySQL容器的IP會發(fā)生變化,連接會失敗。
所以,我們必須借助于docker的網(wǎng)絡功能來解決這個問題,官方文檔:
docker network | Docker Docs
常見命令有:
命令 |
說明 |
文檔地址 |
---|---|---|
docker network create |
創(chuàng)建一個網(wǎng)絡 |
docker network create |
docker network ls |
查看所有網(wǎng)絡 |
docs.docker.com |
docker network rm |
刪除指定網(wǎng)絡 |
docs.docker.com |
docker network prune |
清除未使用的網(wǎng)絡 |
docs.docker.com |
docker network connect |
使指定容器連接加入某網(wǎng)絡 |
docs.docker.com |
docker network disconnect |
使指定容器連接離開某網(wǎng)絡 |
docker network disconnect |
docker network inspect |
查看網(wǎng)絡詳細信息 |
docker network inspect |
教學演示:自定義網(wǎng)絡
# 1.首先通過命令創(chuàng)建一個網(wǎng)絡
docker network create hmall
# 2.然后查看網(wǎng)絡
docker network ls
# 結(jié)果:
NETWORK ID NAME DRIVER SCOPE
639bc44d0a87 bridge bridge local
403f16ec62a2 hmall bridge local
0dc0f72a0fbb host host local
cd8d3e8df47b none null local
# 其中,除了hmall以外,其它都是默認的網(wǎng)絡
# 3.讓dd和mysql都加入該網(wǎng)絡,注意,在加入網(wǎng)絡時可以通過--alias給容器起別名
# 這樣該網(wǎng)絡內(nèi)的其它容器可以用別名互相訪問!
# 3.1.mysql容器,指定別名為db,另外每一個容器都有一個別名是容器名
docker network connect hmall mysql --alias db
# 3.2.db容器,也就是我們的java項目
docker network connect hmall dd
# 4.進入dd容器,嘗試利用別名訪問db
# 4.1.進入容器
docker exec -it dd bash
# 4.2.用db別名訪問
ping db
# 結(jié)果
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms
# 4.3.用容器名訪問
ping mysql
# 結(jié)果:
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
OK,現(xiàn)在無需記住IP地址也可以實現(xiàn)容器互聯(lián)了。
總結(jié):
-
在自定義網(wǎng)絡中,可以給容器起多個別名,默認的別名是容器名本身
-
在同一個自定義網(wǎng)絡中的容器,可以通過別名互相訪問
五、項目部署
好了,我們已經(jīng)熟悉了Docker的基本用法,接下來可以嘗試部署項目了。
在課前資料中已經(jīng)提供了一個黑馬商城項目給大家,如圖:
項目說明:
-
hmall:商城的后端代碼
-
hmall-portal:商城用戶端的前端代碼
-
hmall-admin:商城管理端的前端代碼
部署的容器及端口說明:
項目 |
容器名 |
端口 |
備注 |
---|---|---|---|
hmall |
hmall |
8080 |
黑馬商城后端API入口 |
hmall-portal |
nginx |
18080 |
黑馬商城用戶端入口 |
hmall-admin |
18081 |
黑馬商城管理端入口 |
|
mysql |
mysql |
3306 |
數(shù)據(jù)庫 |
在正式部署前,我們先刪除之前的nginx、dd兩個容器:
docker rm -f nginx dd
mysql容器中已經(jīng)準備好了商城的數(shù)據(jù),所以就不再刪除了。
5.1、部署Java(SpringBoot)項目
hmall
項目是一個maven聚合項目,使用IDEA打開hmall
項目,查看項目結(jié)構(gòu)如圖:
我們要部署的就是其中的hm-service
,其中的配置文件采用了多環(huán)境的方式:
其中的application-dev.yaml
是部署到開發(fā)環(huán)境的配置,application-local.yaml
是本地運行時的配置。
查看application.yaml,你會發(fā)現(xiàn)其中的JDBC地址并未寫死,而是讀取變量:
這兩個變量在application-dev.yaml
和application-local.yaml
中并不相同:
在dev開發(fā)環(huán)境(也就是Docker部署時)采用了mysql作為地址,剛好是我們的mysql容器名,只要兩者在一個網(wǎng)絡,就一定能互相訪問。
我們將項目打包:
結(jié)果:
將hm-service
目錄下的Dockerfile
和hm-service/target
目錄下的hm-service.jar
一起上傳到虛擬機的root
目錄:
部署項目:
# 1.構(gòu)建項目鏡像,不指定tag,則默認為latest
docker build -t hmall .
# 2.查看鏡像
docker images
# 結(jié)果
REPOSITORY TAG IMAGE ID CREATED SIZE
hmall latest 0bb07b2c34b9 43 seconds ago 362MB
docker-demo 1.0 49743484da68 24 hours ago 327MB
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB
# 3.創(chuàng)建并運行容器,并通過--network將其加入hmall網(wǎng)絡,這樣才能通過容器名訪問mysql
docker run -d --name hmall --network hmall -p 8080:8080 hmall
測試,通過瀏覽器訪問:http://你的虛擬機地址:8080/search/list。
5.2、部署前端
hmall-portal
和hmall-admin
是前端代碼,需要基于nginx部署。在課前資料中已經(jīng)給大家提供了nginx的部署目錄:
其中:
-
html
是靜態(tài)資源目錄,我們需要把hmall-portal
以及hmall-admin
都復制進去 -
nginx.conf
是nginx的配置文件,主要是完成對html
下的兩個靜態(tài)資源目錄做代理
我們現(xiàn)在要做的就是把整個nginx目錄上傳到虛擬機的/root
目錄下:
然后創(chuàng)建nginx容器并完成兩個掛載:
-
把
/root/nginx/nginx.conf
掛載到/etc/nginx/nginx.conf
-
把
/root/nginx/html
掛載到/usr/share/nginx/html
由于需要讓nginx同時代理hmall-portal和hmall-admin兩套前端資源,因此我們需要暴露兩個端口:
-
18080:對應hmall-portal
-
18081:對應hmall-admin
命令如下:
docker run -d \
--name nginx \
-p 18080:18080 \
-p 18081:18081 \
-v /root/nginx/html:/etc/nginx/html \
-v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \
--network hmall \
nginx
測試,通過瀏覽器訪問:http://你的虛擬機ip:18080
5.3、DockerCompose
大家可以看到,我們部署一個簡單的java項目,其中包含3個容器:
-
MySQL
-
Nginx
-
Java項目
而稍微復雜的項目,其中還會有各種各樣的其它中間件,需要部署的東西遠不止3個。如果還像之前那樣手動的逐一部署,就太麻煩了。
而Docker Compose就可以幫助我們實現(xiàn)多個相互關聯(lián)的Docker容器的快速部署。它允許用戶通過一個單獨的 docker-compose.yml 模板文件(YAML 格式)來定義一組相關聯(lián)的應用容器。
5.3.1、基本語法
docker-compose.yml文件的基本語法可以參考官方文檔:
Compose file version 3 reference | Docker Docs
docker-compose文件中可以定義多個相互關聯(lián)的應用容器,每一個應用容器被稱為一個服務(service)。由于service就是在定義某個應用的運行時參數(shù),因此與docker run
參數(shù)非常相似。
舉例來說,用docker run部署MySQL的命令如下:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
--network hmall
mysql
如果用docker-compose.yml
文件來定義,就是這樣:
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
networks:
- new
networks:
new:
name: hmall
對比如下:
docker run 參數(shù) |
docker compose 指令 |
說明 |
---|---|---|
--name |
container_name |
容器名稱 |
-p |
ports |
端口映射 |
-e |
environment |
環(huán)境變量 |
-v |
volumes |
數(shù)據(jù)卷配置 |
--network |
networks |
網(wǎng)絡 |
明白了其中的對應關系,相信編寫docker-compose
文件應該難不倒大家。
黑馬商城部署文件:
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
networks:
- hm-net
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall
5.3.2、基本命令
編寫好docker-compose.yml文件,就可以部署項目了。常見的命令:
Overview of docker compose CLI | Docker Docs
基本語法如下:
docker compose [OPTIONS] [COMMAND]
其中,OPTIONS和COMMAND都是可選參數(shù),比較常見的有:
類型 |
參數(shù)或指令 |
說明 |
---|---|---|
Options |
-f |
指定compose文件的路徑和名稱 |
-p |
指定project名稱。project就是當前compose文件中設置的多個service的集合,是邏輯概念 |
|
Commands |
up |
創(chuàng)建并啟動所有service容器 |
down |
停止并移除所有容器、網(wǎng)絡 |
|
ps |
列出所有啟動的容器 |
|
logs |
查看指定容器的日志 |
|
stop |
停止容器 |
|
start |
啟動容器 |
|
restart |
重啟容器 |
|
top |
查看運行的進程 |
|
exec |
在指定的運行中容器中執(zhí)行命令 |
教學演示:文章來源:http://www.zghlxwxcb.cn/news/detail-822943.html
# 1.進入root目錄
cd /root
# 2.刪除舊容器
docker rm -f $(docker ps -qa)
# 3.刪除hmall鏡像
docker rmi hmall
# 4.清空MySQL數(shù)據(jù)
rm -rf mysql/data
# 5.啟動所有, -d 參數(shù)是后臺啟動
docker compose up -d
# 結(jié)果:
[+] Building 15.5s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 358B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:11.0-jre-buster 15.4s
=> [1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c3 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 98B 0.0s
=> CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 0.0s
=> CACHED [3/3] COPY hm-service.jar /app.jar 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:32eebee16acde22550232f2eb80c69d2ce813ed099640e4cfed2193f71 0.0s
=> => naming to docker.io/library/root-hmall 0.0s
[+] Running 4/4
? Network hmall Created 0.2s
? Container mysql Started 0.5s
? Container hmall Started 0.9s
? Container nginx Started 1.5s
# 6.查看鏡像
docker compose images
# 結(jié)果
CONTAINER REPOSITORY TAG IMAGE ID SIZE
hmall root-hmall latest 32eebee16acd 362MB
mysql mysql latest 3218b38490ce 516MB
nginx nginx latest 605c77e624dd 141MB
# 7.查看容器
docker compose ps
# 結(jié)果
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
hmall root-hmall "java -jar /app.jar" hmall 54 seconds ago Up 52 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
mysql mysql "docker-entrypoint.s…" mysql 54 seconds ago Up 53 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp
nginx nginx "/docker-entrypoint.…" nginx 54 seconds ago Up 52 seconds 80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp
打開瀏覽器,訪問:http://yourIp:8080文章來源地址http://www.zghlxwxcb.cn/news/detail-822943.html
到了這里,關于黑馬程序員Docker快速入門到項目部署(學習筆記)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!