Docker 是一種開源的容器化平臺(tái),用于構(gòu)建挽铁、打包她紫、部署和運(yùn)行應(yīng)用程序及其所有依賴的環(huán)境。通過使用 Docker屿储,開發(fā)者可以將應(yīng)用程序及其環(huán)境打包成一個(gè)稱為容器的輕量級(jí)、獨(dú)立的單元够掠。這些容器可以在任何支持 Docker 的環(huán)境中運(yùn)行,確保應(yīng)用在不同環(huán)境之間具有一致的運(yùn)行行為疯潭。
核心概念
容器化技術(shù):Docker 使用容器化技術(shù)來隔離應(yīng)用程序及其依賴的環(huán)境。每個(gè)容器都是一個(gè)獨(dú)立的運(yùn)行單元竖哩,具有自己的文件系統(tǒng)、進(jìn)程空間相叁、網(wǎng)絡(luò)配置等。容器化使得應(yīng)用程序能夠更加輕松地在不同環(huán)境中進(jìn)行部署和遷移增淹。
鏡像:Docker 鏡像是一個(gè)只讀的模板,它包含了應(yīng)用程序運(yùn)行所需的所有文件乌企、依賴虑润、環(huán)境變量等。通過編寫 Dockerfile 文件來定義鏡像的構(gòu)建過程加酵,然后使用 Docker 命令構(gòu)建鏡像拳喻。鏡像可以作為容器的基礎(chǔ),多個(gè)容器可以共享同一個(gè)鏡像猪腕。
Docker 容器:容器是從鏡像創(chuàng)建的實(shí)例冗澈,它是一個(gè)運(yùn)行的進(jìn)程,具有獨(dú)立的命名空間陋葡、文件系統(tǒng)和資源限制渗柿。容器可以輕松地啟動(dòng)、停止、刪除朵栖,可以在不同的主機(jī)和環(huán)境中移植颊亮,從而實(shí)現(xiàn)環(huán)境的一致性。
Docker Hub:Docker Hub 是一個(gè)公共的鏡像倉(cāng)庫(kù)陨溅,開發(fā)者可以在其中找到各種常用的鏡像终惑,也可以上傳自己構(gòu)建的鏡像供他人使用。此外门扇,Docker Hub 還支持私有鏡像倉(cāng)庫(kù)雹有,用于組織內(nèi)部的鏡像管理。
Docker Compose:Docker Compose 是一個(gè)工具臼寄,允許你使用 YAML 文件定義多個(gè)容器的配置和關(guān)系霸奕,以便一鍵啟動(dòng)、停止多個(gè)容器吉拳,實(shí)現(xiàn)復(fù)雜應(yīng)用的編排质帅。
跨平臺(tái)和一致性:由于 Docker 容器在不同平臺(tái)上運(yùn)行時(shí)依賴的是相同的容器引擎,因此可以實(shí)現(xiàn)跨平臺(tái)的一致性留攒。開發(fā)者可以在開發(fā)煤惩、測(cè)試和生產(chǎn)環(huán)境中使用相同的容器,減少了由環(huán)境差異引起的問題炼邀。
快速部署和擴(kuò)展:Docker 容器的輕量級(jí)特性使得它們可以快速啟動(dòng)和停止魄揉,從而實(shí)現(xiàn)快速部署、回滾和擴(kuò)展洛退。這對(duì)于應(yīng)對(duì)流量峰值和高可用性要求非常有利杰标。
常用命令
docker images 本地的鏡像
docker exec -it xxx /bin/bash 進(jìn)入xxx容器
docker start xxx 啟動(dòng)xxx容器
docker stop xxx 停止xxx容器
docker restart xxx 重啟xxx容器
docker rm xxx 刪除xxx容器
docker rmi xxx 刪除xxx鏡像
docker search xxx 搜索xxx容器
docker pull xxx 拉取xxx鏡像
docker run -d --name my-service xxx 運(yùn)行拉取的xxx鏡像在旱,-d 表示在后臺(tái)運(yùn)行容器桶蝎,--name 指定容器的名稱
docker logs xxx 查看xxx容器的日志
docker stats 統(tǒng)計(jì)各個(gè)docker服務(wù)占用的資源
docker cp xxx:file ~ 將xxx容器file文件copy到當(dāng)前文件夾
docker inspect xxx 查看xxx容器詳細(xì)信息
docker system prune -a 這個(gè)命令將清理整個(gè)系統(tǒng),并且只會(huì)保留真正在使用的鏡像噪服,容器粘优,數(shù)據(jù)卷以及網(wǎng)絡(luò),因此需要格外謹(jǐn)慎丹墨,防止一些備份或者用于回滾的鏡像被刪除贩挣。
私有倉(cāng)庫(kù)上傳鏡像步驟:1.給已有鏡像打一個(gè)tag没酣。2.登錄私有倉(cāng)庫(kù)裕便。3.上傳鏡像到私有倉(cāng)庫(kù) ps:xxx為鏡像名稱,docker-hub.company.cn為對(duì)應(yīng)的私服地址
docker tag xxx docker-hub.company.cn/xxx
docker login -u user-p pass docker-hub.company.cn
docker push docker-hub.company.cn/xxx
如何構(gòu)建一個(gè)鏡像
創(chuàng)建 Dockerfile
在你的項(xiàng)目目錄下創(chuàng)建一個(gè)名為 Dockerfile 的文件挂疆,用于定義構(gòu)建鏡像的步驟和配置。在 Dockerfile 中漏设,你可以指定基礎(chǔ)鏡像郑口、復(fù)制文件盾鳞、設(shè)置環(huán)境變量等腾仅。以下是一個(gè)簡(jiǎn)單示例 Dockerfile(以一個(gè)簡(jiǎn)單的 Python Web 應(yīng)用為例):
# 基礎(chǔ)鏡像
FROM python:3.8
# 工作目錄
WORKDIR /app
# 復(fù)制當(dāng)前目錄下的文件到容器的 /app 目錄
COPY . /app
# 安裝應(yīng)用所需的依賴
RUN pip install -r requirements.txt
# 暴露容器的端口
EXPOSE 80
# 啟動(dòng)應(yīng)用
CMD ["python", "app.py"]
常用命令:
FROM:指定基礎(chǔ)鏡像推励;
WORKDIR:設(shè)置工作目錄,后續(xù)的命令將在該目錄中執(zhí)行稿黄。
COPY 和 ADD:用于將文件從主機(jī)復(fù)制到容器中杆怕。COPY 更常用陵珍,用于簡(jiǎn)單的文件復(fù)制,而 ADD 更強(qiáng)大朝墩,可以自動(dòng)解壓縮文件收苏,也支持從url嘗試下載資源鹿霸。
RUN:用于在鏡像構(gòu)建過程中執(zhí)行命令秆乳,可以安裝軟件包屹堰、設(shè)置環(huán)境等。
ENV:設(shè)置環(huán)境變量睦袖。
EXPOSE:聲明容器將監(jiān)聽的端口號(hào)馅笙。
CMD 和 ENTRYPOINT:定義容器啟動(dòng)時(shí)執(zhí)行的命令董习。CMD 可以被docker run命令行中的命令覆蓋皿淋,而 ENTRYPOINT 不會(huì)被覆蓋恬试。
USER:指定運(yùn)行命令的用戶名忘渔。
構(gòu)建鏡像
使用 docker build 命令來構(gòu)建鏡像。你需要指定 Dockerfile 的路徑(當(dāng)前目錄或其他路徑)散址,還可以使用 -t 參數(shù)來為鏡像設(shè)置一個(gè)標(biāo)簽。
docker build -t my-python-app .
在上述命令中瞪浸,-t 參數(shù)用于設(shè)置鏡像的標(biāo)簽对蒲,my-python-app 是鏡像的名稱蹈矮,. 表示 Dockerfile 的路徑為當(dāng)前目錄泛鸟。
多階段構(gòu)建
Docker 提供了一種多階段構(gòu)建的功能踊东,其中可以使用不同的基礎(chǔ)鏡像來構(gòu)建不同階段的鏡像闸翅。
# 構(gòu)建階段
FROM golang:1.16 as builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# 運(yùn)行階段
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
在上面的示例中坚冀,我們定義了兩個(gè)階段:
- 第一個(gè)階段使用 golang:1.16 作為基礎(chǔ)鏡像遗菠,構(gòu)建了一個(gè) Go 應(yīng)用程序华蜒,并將其命名為 builder叭喜。
- 第二個(gè)階段使用 alpine:latest 作為基礎(chǔ)鏡像,運(yùn)行了最終的應(yīng)用程序譬涡,并從第一個(gè)階段的構(gòu)建中復(fù)制了編譯后的二進(jìn)制文件涡匀。
通過這種方式陨瘩,我們可以確保最終的鏡像只包含運(yùn)行時(shí)所需的內(nèi)容,而不包含構(gòu)建工具和源代碼帚湘,從而減小了鏡像的大小大诸。
網(wǎng)絡(luò)配置
Docker 的網(wǎng)絡(luò)配置允許你在容器之間以及容器與主機(jī)之間建立網(wǎng)絡(luò)連接贯卦,使得容器能夠相互通信,與外部世界進(jìn)行交互脸侥,以及實(shí)現(xiàn)不同網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)睁枕。Docker 提供了多種網(wǎng)絡(luò)模式和選項(xiàng),讓你能夠根據(jù)應(yīng)用需求進(jìn)行靈活配置注簿。
默認(rèn)網(wǎng)絡(luò)模式:Docker 安裝后诡渴,默認(rèn)創(chuàng)建一個(gè)名為 bridge 的網(wǎng)絡(luò)妄辩,這是一種默認(rèn)網(wǎng)絡(luò)模式山上,允許容器之間通過 IP 進(jìn)行通信。每個(gè)容器會(huì)自動(dòng)分配一個(gè)隨機(jī) IP哮伟,容器內(nèi)的應(yīng)用可以使用該 IP 進(jìn)行通信楞黄。這種模式適用于大多數(shù)單機(jī)應(yīng)用場(chǎng)景抡驼。
主機(jī)網(wǎng)絡(luò)模式:在主機(jī)網(wǎng)絡(luò)模式下致盟,容器和主機(jī)共享同一個(gè)網(wǎng)絡(luò)命名空間,容器直接使用主機(jī)的網(wǎng)絡(luò)接口蚣录。這樣容器可以使用主機(jī)的 IP 地址,但容器之間仍然需要通過端口來區(qū)分荔泳。
容器網(wǎng)絡(luò)模式:在容器網(wǎng)絡(luò)模式下玛歌,所有容器共享同一個(gè)網(wǎng)絡(luò)命名空間擎椰,容器可以直接使用彼此的 IP 地址达舒。這種模式適用于需要高度互通的容器集群巩搏。
自定義橋接網(wǎng)絡(luò):你可以創(chuàng)建自定義的橋接網(wǎng)絡(luò)贯底,允許容器在該網(wǎng)絡(luò)中通信。這使得容器可以使用容器名進(jìn)行通信笙什,而不僅僅是 IP 地址琐凭。
Overlay 網(wǎng)絡(luò):Overlay 網(wǎng)絡(luò)是用于跨主機(jī)容器的網(wǎng)絡(luò)模式顿仇,允許不同主機(jī)上的容器之間通過虛擬網(wǎng)絡(luò)進(jìn)行通信臼闻。這在容器編排和集群管理中很有用述呐,比如 Docker Swarm 和 Kubernetes乓搬。
MacVLAN 網(wǎng)絡(luò):MacVLAN 網(wǎng)絡(luò)模式允許容器擁有自己的 MAC 地址,從而使得容器可以直接連接到物理網(wǎng)絡(luò)进肯,實(shí)現(xiàn)容器與外部網(wǎng)絡(luò)的通信江掩。
網(wǎng)絡(luò)別名和服務(wù)發(fā)現(xiàn):Docker 提供了網(wǎng)絡(luò)別名和內(nèi)置的 DNS 服務(wù)發(fā)現(xiàn)機(jī)制环形,使容器能夠通過容器名或服務(wù)名來進(jìn)行通信,而不僅僅依賴于 IP 地址萨咕。
端口映射:Docker 允許你將容器內(nèi)部的端口映射到主機(jī)上的端口危队,從而允許外部網(wǎng)絡(luò)通過主機(jī)的 IP 地址和映射的端口來訪問容器內(nèi)部的應(yīng)用钙畔。
# 創(chuàng)建一個(gè)使用默認(rèn) bridge 網(wǎng)絡(luò)的容器
docker run -d --name my-container nginx
# 使用主機(jī)網(wǎng)絡(luò)模式啟動(dòng)容器
docker run -d --network host nginx
# 創(chuàng)建容器網(wǎng)絡(luò)模式下的容器
docker run -d --name container-1 nginx
docker run -d --name container-2 --network container:container-1 nginx
# 創(chuàng)建一個(gè)自定義的橋接網(wǎng)絡(luò)
docker network create my-bridge-network
# 啟動(dòng)容器并連接到自定義網(wǎng)絡(luò)
docker run -d --network my-bridge-network --name container-1 nginx
docker run -d --network my-bridge-network --name container-2 nginx
# 在 Docker Swarm 中創(chuàng)建一個(gè) Overlay 網(wǎng)絡(luò)
docker network create --driver overlay my-overlay-network
# 啟動(dòng)服務(wù)并連接到 Overlay 網(wǎng)絡(luò)
docker service create --network my-overlay-network --name my-service nginx
# 創(chuàng)建 MacVLAN 網(wǎng)絡(luò)
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 my-macvlan-network
# 啟動(dòng)容器并連接到 MacVLAN 網(wǎng)絡(luò)
docker run -d --network my-macvlan-network --name container-with-macvlan nginx
# 啟動(dòng)容器并連接到網(wǎng)絡(luò)
docker run -d --network my-bridge-network --network-alias my-alias nginx
# 在容器內(nèi)使用網(wǎng)絡(luò)別名
docker exec -it container-id /bin/bash
ping my-alias
# 啟動(dòng)容器并將容器內(nèi)部的端口映射到主機(jī)端口
docker run -d -p 8080:80 --name my-container-with-port nginx
數(shù)據(jù)持久化
在 Docker 中實(shí)現(xiàn)數(shù)據(jù)持久化有多種方式盅弛,這些方式可以確保容器內(nèi)的數(shù)據(jù)在容器被停止挪鹏、銷毀讨盒、重新創(chuàng)建或升級(jí)時(shí)得以保留步责。以下是幾種常見的 Docker 數(shù)據(jù)持久化方式:
數(shù)據(jù)卷(Volumes)
數(shù)據(jù)卷是一種特殊的文件系統(tǒng)蔓肯,可以將其掛載到容器內(nèi)的特定路徑蔗包,使得容器內(nèi)的數(shù)據(jù)可以持久化保存在宿主機(jī)上。Docker 容器內(nèi)的數(shù)據(jù)卷與容器外部的文件系統(tǒng)隔離舟陆,這樣可以避免容器的生命周期影響數(shù)據(jù)秦躯。數(shù)據(jù)卷還可以被容器之間共享踱承。
卷分為臨時(shí)卷和持久卷。主要區(qū)別在于數(shù)據(jù)存儲(chǔ)的持久性和生命周期毡琉。以下是它們的區(qū)別和如何區(qū)分:
1. 臨時(shí)卷(臨時(shí)數(shù)據(jù))
- 生命周期:臨時(shí)卷只在容器運(yùn)行期間存在桅滋,當(dāng)容器被刪除時(shí)丐谋,臨時(shí)卷也會(huì)被刪除号俐。
- 用途:通常用于存儲(chǔ)容器內(nèi)的短期數(shù)據(jù)吏饿,比如緩存蔬浙、日志等畴博。
- 創(chuàng)建方式:臨時(shí)卷是由 Docker 自動(dòng)管理的,不需要用戶明確創(chuàng)建官疲。
- 掛載方式:使用 docker run 命令中的 -v 或 --mount 參數(shù)時(shí)途凫,如果指定了容器內(nèi)部的路徑颖榜,而沒有指定卷名煤裙,Docker 會(huì)自動(dòng)創(chuàng)建一個(gè)臨時(shí)卷硼砰。
示例
docker run -v /container/path ubuntu
2. 持久卷(持久數(shù)據(jù))
- 生命周期:持久卷獨(dú)立于容器的生命周期题翰。當(dāng)容器刪除時(shí)冯事,持久卷依然存在昵仅,直到顯式刪除摔笤。
- 用途:用于存儲(chǔ)需要持久保存的數(shù)據(jù)吕世,比如數(shù)據(jù)庫(kù)的數(shù)據(jù)梯投、用戶上傳的文件等分蓖。
- 創(chuàng)建方式:持久卷需要用戶創(chuàng)建或由 Docker 管理漓帚,通過 docker volume create 命令。
- 掛載方式:通過 docker run 或 docker-compose 文件午磁,指定已有的持久卷掛載到容器中尝抖。
示例:
docker volume create mydata
docker run -v mydata:/container/path ubuntu
主機(jī)文件系統(tǒng)掛載(Bind Mounts)
主機(jī)文件系統(tǒng)掛載允許你將宿主機(jī)上的目錄或文件掛載到容器內(nèi),實(shí)現(xiàn)數(shù)據(jù)的共享和持久化迅皇。這種方式適用于需要在容器和宿主機(jī)之間共享數(shù)據(jù)的情況昧辽。
# 運(yùn)行容器并使用主機(jī)文件系統(tǒng)掛載
docker run -d -v /path/on/host:/app/data myimage
共享存儲(chǔ)驅(qū)動(dòng)(Shared Storage Drivers)
如果你需要在多個(gè) Docker 容器之間實(shí)現(xiàn)數(shù)據(jù)共享和持久化,可以使用共享存儲(chǔ)驅(qū)動(dòng)登颓,如 NFS(Network File System)或 CIFS(Common Internet File System)
Docker compose
當(dāng)你需要管理多個(gè) Docker 容器并確保它們能夠協(xié)同工作時(shí)搅荞,Docker Compose 是一個(gè)非常有用的工具。它允許你使用一個(gè)單獨(dú)的配置文件來定義、配置和運(yùn)行多個(gè)相關(guān)的容器咕痛,從而簡(jiǎn)化了容器編排的過程痢甘。
version: '3'
services:
webapp:
image: python:3.8
command: python app.py
ports:
- "5000:5000"
volumes:
- ./webapp:/app
# 聲明容器之間的依賴順序,當(dāng)一個(gè)服務(wù)依賴于其他服務(wù)時(shí),它會(huì)先啟動(dòng)那些依賴的服務(wù)砾医,然后再啟動(dòng)自身
depends_on:
- database
environment:
MYSQL_HOST: database
MYSQL_PORT: 3306
MYSQL_USER: root
MYSQL_PASSWORD: example
MYSQL_DB: mydb
database:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: mydb
在這個(gè)示例中怖亭,我們定義了兩個(gè)服務(wù):webapp 和 database。webapp 服務(wù)使用 Python 3.8 鏡像倾芝,將當(dāng)前目錄下的 webapp 目錄掛載到容器的 /app 目錄,以便實(shí)時(shí)更新應(yīng)用代碼。它將應(yīng)用程序命令設(shè)置為 python app.py,并將容器的 5000 端口映射到主機(jī)的 5000 端口茂契。還定義了數(shù)據(jù)庫(kù)的環(huán)境變量,以便連接到數(shù)據(jù)庫(kù)服務(wù)。database 服務(wù)使用 MySQL 5.7 鏡像旁振,并設(shè)置了數(shù)據(jù)庫(kù)的 root 密碼和數(shù)據(jù)庫(kù)名稱梢薪。
要運(yùn)行這個(gè)示例秋泄,只需在終端中導(dǎo)航到包含 docker-compose.yml 文件的目錄,然后運(yùn)行以下命令:
docker-compose up
這將啟動(dòng)兩個(gè)服務(wù),你的 Web 應(yīng)用將在 http://localhost:5000 上訪問屠缭,可以通過該 URL 進(jìn)行訪問何暮。如果你要停止并銷毀服務(wù),可運(yùn)行以下命令:
docker-compose down
也可以單獨(dú)啟動(dòng)/停止某個(gè)項(xiàng)目玻蝌,如下示例:
docker-compose up -d database
docker-compose stop database
此外,在 Docker Compose 的同一個(gè)配置文件中阳欲,所有服務(wù)默認(rèn)會(huì)在一個(gè)共享的自定義網(wǎng)絡(luò)中運(yùn)行筒愚,它們可以通過服務(wù)名稱來相互引用和通信陆淀。這意味著你可以在 Docker Compose 定義的不同服務(wù)之間,使用服務(wù)名稱作為主機(jī)名進(jìn)行網(wǎng)絡(luò)通信鳄袍。
原理是當(dāng)你運(yùn)行 docker-compose up 時(shí),Docker Compose 會(huì)自動(dòng)為這些服務(wù)創(chuàng)建一個(gè)默認(rèn)的橋接網(wǎng)絡(luò)(通常命名為 <項(xiàng)目名>_default),并將所有服務(wù)都連接到這個(gè)網(wǎng)絡(luò)中。
Jib Maven
Jib Maven 插件(Jib Maven Plugin)是 Google 開源的一個(gè)構(gòu)建工具沪编,用于將 Java 應(yīng)用程序容器化并推送到容器注冊(cè)表相嵌,如 Docker Hub捏雌、Google Container Registry 等纬傲。它的主要目標(biāo)是簡(jiǎn)化 Java 應(yīng)用程序的容器化過程净嘀,特別是在使用 Maven 構(gòu)建 Java 項(xiàng)目時(shí)膜眠。Jib Maven 插件與傳統(tǒng)的 Dockerfile 不同,它不需要你編寫 Dockerfile 或在本地安裝 Docker抑钟,而是直接從 Maven 項(xiàng)目構(gòu)建的內(nèi)容創(chuàng)建容器鏡像。
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.7.0</version>
<configuration>
<from>
<!--基礎(chǔ)鏡像-->
<image>xxxxx</image>
</from>
<to>
<!--目標(biāo)鏡像registry地址-->
<image>hub.docker.com/xxx</image>
<tags>
<!--版本號(hào)-->
<tag>5</tag>
</tags>
<auth>
<username>xxx</username>
<password>pass</password>
</auth>
</to>
<container>
<mainClass>xx.xx.Application</mainClass>
</container>
</configuration>
</plugin>
上面是一個(gè)簡(jiǎn)單的例子涧衙,只需運(yùn)行 mvn compile jib:build 命令便可構(gòu)建鏡像并推送。