從入門到精通Docker Compose 輕松部署微服務(wù)實(shí)戰(zhàn)教程
從零到一:Docker Compose 輕松部署微服務(wù)實(shí)戰(zhàn)
今天實(shí)踐一下使用Docker Compose部署一個(gè)微服務(wù)項(xiàng)目。
項(xiàng)目包括docker compose部署的代碼都放在了我的github上:https://github.com/cra358/demo
首先簡(jiǎn)單寫一個(gè)微服務(wù)項(xiàng)目,主要技術(shù)棧:Spring Cloud Alibaba、redis、Mysql、Gateway、SaToken
主要就是用戶登陸積分記錄功能。用戶每登陸系統(tǒng)一次,用戶登陸積分+1。
服務(wù)劃分:
- gatway主要實(shí)現(xiàn)登陸校驗(yàn)。
- user實(shí)現(xiàn)用戶注冊(cè)、退出、積分查詢?cè)鲩L(zhǎng)功能。

容器劃分:
環(huán)境容器:nacos、mysql、redis
服務(wù)容器:gateway、user
服務(wù)打包package:
先雙擊clean,清理target目錄文件,再雙擊package文件,點(diǎn)擊右上角的>中的帶斜線的圈可以跳過(guò)test。

在target目錄中可以找到對(duì)應(yīng)的jar包。確定沒(méi)有問(wèn)題后就可以開(kāi)始部署了。
安裝Docker(略)
Docker 使用的版本是Docker version 27.5.0,安裝完成后在pull一下mysql、redis和nacos的鏡像,方便后面創(chuàng)建環(huán)境容器。本次使用的是mysql8.0、redis7.2.3、nacos v2.2.0版本。

Docker Compose安裝
在選擇安裝版本時(shí),需要注意Docker Compose 版本和Docker版本對(duì)應(yīng)。我使用的Docker Compose版本是Docker Compose version v2.30.0
- https://github.com/docker/compose/releases/tag/v2.30.0。到這里下載Docker Compose文件。

- 將文件移動(dòng)到:/usr/local/bin/docker-compose
sudo cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose
- 添加可執(zhí)行權(quán)限
chmod +x /usr/local/bin/docker-compose
- 測(cè)試安裝成功
docker-compose --version

安裝成功后,正式準(zhǔn)備部署。在項(xiàng)目目錄的docker目錄中:

docker下的demo目錄存放兩個(gè)服務(wù)模塊的我們之前打包生成好的jar包和Dockerfile文件:

現(xiàn)在,我們需要為每個(gè)微服務(wù)編寫 Dockerfile內(nèi)容,用于構(gòu)建 Docker 鏡像。Dockerfile 定義了鏡像的構(gòu)建過(guò)程,包括基礎(chǔ)鏡像、依賴安裝、代碼復(fù)制、啟動(dòng)命令等。
為微服務(wù)編寫Dockerfile文件
- user
# 基礎(chǔ)鏡像 FROM openjdk:17 # 掛載目錄,就是容器中的目錄 VOLUME /home/user # 創(chuàng)建目錄,也是容器中的目錄 RUN mkdir -p /home/user # 指定路徑 WORKDIR /home/user # 復(fù)制jar文件到容器指定路徑,就是把宿主機(jī)中的./jar/user.jar文件復(fù)制到容器/home/user/user.jar中 COPY ./jar/user.jar /home/user/user.jar # 啟動(dòng)用戶服務(wù) ENTRYPOINT ["java","-jar","user.jar"]
- gateway
# 基礎(chǔ)鏡像 FROM openjdk:17 # 掛載目錄 VOLUME /home/gateway # 創(chuàng)建目錄 RUN mkdir -p /home/gateway # 指定路徑 WORKDIR /home/gateway # 復(fù)制jar文件到路徑 COPY ./jar/gateway.jar /home/gateway/gateway.jar # 啟動(dòng)用戶服務(wù) ENTRYPOINT ["java","-jar","gateway.jar"]
完成上述步驟后,準(zhǔn)備環(huán)境容器的Docker文件和一些配置:
mysql容器準(zhǔn)備:

在db目錄下存放項(xiàng)目所需的初始數(shù)據(jù)庫(kù)表。同時(shí)由于nacos配置依賴于mysql存放相關(guān)數(shù)據(jù),也在這里存放一個(gè)nacos_config.sql文件,文件內(nèi)容直接網(wǎng)上照抄即可。
db.sql文件如下:
CREATE DATABASE IF NOT EXISTS `demo_user` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `demo_user`;
-- 刪除已存在的表(謹(jǐn)慎使用)
DROP TABLE IF EXISTS `user`;
-- 創(chuàng)建 user 表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶ID,主鍵',
`username` varchar(50) NOT NULL COMMENT '用戶名',
`password` varchar(255) NOT NULL COMMENT '密碼(存儲(chǔ)加密后的密碼)',
`score` int(11) NOT NULL DEFAULT '0' COMMENT '用戶積分',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`) COMMENT '用戶名唯一索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶表';編寫mysql容器的Dockerfile:
# 基礎(chǔ)鏡像,就是docker images命令下我們之前pull的mysql鏡像,據(jù)此創(chuàng)建mysql容器 FROM mysql:8.0 # 執(zhí)行sql腳本 # `/docker-entrypoint-initdb.d/`是MySQL官方鏡像中的一個(gè)特殊目錄,用于存放初始化數(shù)據(jù)庫(kù)的腳本文件。 # 把剛剛的兩個(gè)sql文件存放到mysql容器中 ADD ./db/*.sql /docker-entrypoint-initdb.d/
- redis容器準(zhǔn)備:

在docker/redis/conf目錄下寫一個(gè)redis配置文件:redis.conf,這里只寫了一個(gè)密碼:
requirepass 1234
同樣,編寫redis容器的Dockerfile:
# 基礎(chǔ)鏡像 FROM redis:7.2.3 # 掛載目錄 VOLUME /home/demo/redis # 創(chuàng)建目錄 RUN mkdir -p /home/demo/redis # 指定路徑 WORKDIR /home/demo/redis # 復(fù)制剛剛的redis.conf文件到容器指定路徑 COPY ./conf/redis.conf /home/demo/redis/redis.conf
- nacos容器準(zhǔn)備:

在docker/nacos/conf中編寫nacos配置文件:application.properties
spring.datasource.platform=mysql
spring.sql.init.platform=mysql
db.num=1
# 這里的nacos_config就是nacos在mysql容器中使用到的數(shù)據(jù)庫(kù),和前面的nacos_config.sql中創(chuàng)建出來(lái)的數(shù)據(jù)庫(kù)要一致
# 下面的配置不一樣有可能會(huì)導(dǎo)致意想不到的錯(cuò)誤
db.url.0=jdbc:mysql://demo-mysql:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
# 制定用戶、密碼
db.user.0=root
db.password.0=20041111
# 這里后面的直接復(fù)制就可以了
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000
management.endpoints.web.exposure.include=*
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir=/home/demo/nacos/tomcat/logs
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=false
nacos.core.auth.default.token.expire.seconds=18000
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
nacos.core.auth.caching.enabled=true
nacos.core.auth.enable.userAgentAuthWhite=false
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security
nacos.istio.mcp.server.enabled=false編寫nacos的Dockerfile文件:
# 基礎(chǔ)鏡像 FROM nacos/nacos-server:v2.2.0 # 復(fù)制剛剛的application.properties文件到nacos容器的制定路徑 COPY ./conf/application.properties /home/nacos/conf/application.properties
到此,我們就準(zhǔn)備好了環(huán)境容器和服務(wù)容器的準(zhǔn)備工作。
編寫 DockerCompose.yml 文件
version: '3'
services:
demo-nacos:
# 容器名
container_name: demo-nacos
image: nacos/nacos-server:v2.2.0
build:
context: ./nacos
environment:
- MODE=standalone
# 使用 mysql 作為數(shù)據(jù)庫(kù)
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=demo-mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=20041111
# 設(shè)置連接 mysql 的連接參數(shù)
- MYSQL_DB_PARAM="characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrievalyaml=true"
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
# 要暴露三個(gè)端口,至于為什么,可以網(wǎng)上查下看看
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
privileged: true
networks:
- demo-network
# nacos依賴于mysql先啟動(dòng)成功
depends_on:
demo-mysql:
condition: service_healthy
# - demo-mysql
demo-mysql:
# 容器名
container_name: demo-mysql
# 鏡像
image: mysql:8.0
build:
context: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
- ./mysql/db:/docker-entrypoint-initdb.d/
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
privileged: true
networks:
- demo-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 5
environment:
MYSQL_ROOT_PASSWORD: '20041111'
demo-redis:
container_name: demo-redis
image: redis:7.2.3
build:
context: ./redis
dockerfile: Dockerfile
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/demo/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/demo/redis/redis.conf
networks:
- demo-network
# 網(wǎng)關(guān)服務(wù)容器
demo-gateway:
container_name: demo-gateway
build:
context: ./demo/gateway
dockerfile: Dockerfile
ports:
- "8000:8000"
depends_on:
- demo-redis
- demo-nacos
networks:
- demo-network
# 用戶服務(wù)容器
demo-user:
container_name: demo-user
build:
context: ./demo/user
dockerfile: Dockerfile
# 端口映射
ports:
- "8001:8001"
depends_on:
- demo-redis
- demo-mysql
- demo-nacos
networks:
- demo-network
# 確保都在同一個(gè)網(wǎng)絡(luò)下
networks:
demo-network:
driver: bridgesh腳本
上述工作完成后,我們寫一個(gè)sh腳本,方便我們清理復(fù)制jar包、運(yùn)行docker-compose.yml文件來(lái)啟動(dòng)容器。

- cleanjar.sh
#!/bin/bash # 刪除jar文件 echo "開(kāi)始清理jar文件" rm -f ../demo/gateway/jar/gateway.jar rm -f ../demo/user/jar/user.jar echo "清理完成"
- copy.sh
#!/bin/bash # 創(chuàng)建目標(biāo)目錄 mkdir -p ../mysql/db mkdir -p ../demo/gateway/jar mkdir -p ../demo/user/jar # 復(fù)制項(xiàng)目db目錄下的sql文件到docker/mysql/db目錄中 echo "begin copy sql " cp ../../sql/db.sql ../mysql/db echo "end copy sql " # 復(fù)制target目錄下的jar文件到docker目錄下的demo的jar目錄中 echo "begin copy jar " cp ../../gateway/target/com.chenxw.demo.gateway-1.0-SNAPSHOT.jar ../demo/gateway/jar/gateway.jar cp ../../user/target/com.chenxw.demo.user-1.0-SNAPSHOT.jar ../demo/user/jar/user.jar echo "end copy jar "
- deploy.sh:Docker Compose運(yùn)行腳本
#!/bin/sh
# 使用說(shuō)明,用來(lái)提示輸入?yún)?shù)
usage(){
echo "Usage: sh 執(zhí)行腳本.sh [base|services|stop|rm]"
exit 1
}
# 啟動(dòng)基礎(chǔ)環(huán)境(必須)
base(){
docker-compose up -d demo-mysql demo-redis demo-nacos
}
# 啟動(dòng)程序模塊(必須)
services(){
docker-compose up -d demo-gateway demo-user
}
# 關(guān)閉所有環(huán)境/模塊
stop(){
docker-compose stop
}
# 刪除所有環(huán)境/模塊
rm(){
docker-compose rm
}
# 根據(jù)輸入?yún)?shù),選擇執(zhí)行對(duì)應(yīng)方法,不輸入則執(zhí)行使用說(shuō)明
case "$1" in
"base")
base
;;
"services")
services
;;
"stop")
stop
;;
"rm")
rm
;;
*)
usage
;;
esac到此,所有準(zhǔn)備工作都完成了。但是我們要注意,在項(xiàng)目的apppication.yml文件中,我們要把127.0.0.1或者localhost改成指定容器名,每個(gè)容器都有自己的ip。比如這里要連接mysql就改成demo-mysql,要連接redis就改成demo-redis,要配置nacos地址就改成demo-nacos
比如gateway服務(wù)中的apppication.yml文件:
server:
port: 8000 # 指定啟動(dòng)端口
spring:
application:
name: demo-gateway # 容器名稱,就是我們?cè)赿ocker-compose.yml中指定的container_name
cloud:
config:
enabled: false
nacos:
discovery:
enabled: true # 啟用服務(wù)發(fā)現(xiàn)
group: DEFAULT_GROUP # 所屬組
namespace: demo # 命名空間
server-addr: demo-nacos:8848 # 指定 Nacos 配置中心的服務(wù)器地址
username: nacos
password: nacos
gateway:
routes:
- id: user
uri: lb://demo-user
predicates:
- Path=/user/**
filters:
- StripPrefix=0
data:
redis:
database: 1 # Redis 數(shù)據(jù)庫(kù)索引
host: demo-redis # Redis 服務(wù)器地址
port: 6379 # Redis 服務(wù)器連接端口
password: 1234 # Redis 服務(wù)器連接密碼(默認(rèn)為空)
timeout: 5s # 讀超時(shí)時(shí)間
connect-timeout: 5s # 鏈接超時(shí)時(shí)間
lettuce:
pool:
max-active: 200 # 連接池最大連接數(shù)
max-wait: -1ms # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)
min-idle: 0 # 連接池中的最小空閑連接
max-idle: 10 # 連接池中的最大空閑連接
############## Sa-Token 配置 (文檔: https://sa-token.cc) ##############
sa-token:
# token 名稱(同時(shí)也是 cookie 名稱)
token-name: Authorization
# token前綴
token-prefix: Bearer
# token 有效期(單位:秒) 默認(rèn)30天,-1 代表永久有效
timeout: 2592000
# token 最低活躍頻率(單位:秒),如果 token 超過(guò)此時(shí)間沒(méi)有訪問(wèn)系統(tǒng)就會(huì)被凍結(jié),默認(rèn)-1 代表不限制,永不凍結(jié)
active-timeout: -1
# 是否允許同一賬號(hào)多地同時(shí)登錄 (為 true 時(shí)允許一起登錄, 為 false 時(shí)新登錄擠掉舊登錄)
is-concurrent: true
# 在多人登錄同一賬號(hào)時(shí),是否共用一個(gè) token (為 true 時(shí)所有登錄共用一個(gè) token, 為 false 時(shí)每次登錄新建一個(gè) token)
is-share: true
# token 風(fēng)格(默認(rèn)可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
token-style: random-32
# 是否輸出操作日志
is-log: true微服務(wù),啟動(dòng)!
運(yùn)行cleanjar.sh、copy.sh復(fù)制sql、jar包。
運(yùn)行sh deploy.sh base,啟動(dòng)環(huán)境容器!

在IDEA服務(wù)中也可以看到環(huán)境容器啟動(dòng)成功:

運(yùn)行sh deploy.sh services,啟動(dòng)服務(wù)容器!

服務(wù)容器也啟動(dòng)成功:

在nacos控制臺(tái)查看demo-gateway和demo-user服務(wù)是否注冊(cè)成功:

兩個(gè)應(yīng)用都注冊(cè)到nacos中了,來(lái)看下各個(gè)容器的ip:

從網(wǎng)關(guān)127.19.0.5訪問(wèn):試下注冊(cè)、登陸、積分查詢、退出接口都沒(méi)有問(wèn)題。
注冊(cè):

登陸:

查詢:

退出:

至此,docker compose部署微服務(wù)就完成了。
其實(shí)這個(gè)過(guò)程中還是會(huì)遇到各種奇奇怪怪的錯(cuò)誤,可以用cursor幫忙理解整個(gè)報(bào)錯(cuò)原因,一步步梳理,效率嘎嘎高!
參考資料:https://github.com/timeless157/timeless-order-pay-parent.git
到此這篇關(guān)于從入門到精通Docker Compose 輕松部署微服務(wù)實(shí)戰(zhàn)教程的文章就介紹到這了,更多相關(guān)docker compose部署微服務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker給容器添加新端口映射的兩種方法及常用命令舉例詳解
Docker是一個(gè)開(kāi)源的應(yīng)用容器引擎,允許開(kāi)發(fā)者打包和發(fā)布應(yīng)用到任何流行的Linux機(jī)器上,并實(shí)現(xiàn)虛擬化,這篇文章主要介紹了Docker給容器添加新端口映射的兩種方法及常用命令的相關(guān)資料,需要的朋友可以參考下2025-03-03
Docker部署Go項(xiàng)目發(fā)布鏡像到倉(cāng)庫(kù)
這篇文章主要為大家介紹了Docker部署Go項(xiàng)目發(fā)布鏡像到倉(cāng)庫(kù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
docker-compose:未找到命令的檢查步驟和修復(fù)
最近在使用docker時(shí),有不少人遇到了一個(gè)問(wèn)題,在容器中找不到docker命令,這個(gè)問(wèn)題可能會(huì)導(dǎo)致一些困惑和疑惑,這篇文章主要介紹了docker-compose:未找到命令的檢查步驟和修復(fù)的相關(guān)資料,需要的朋友可以參考下2024-08-08
使用docker部署django技術(shù)棧項(xiàng)目的方法步驟
這篇文章主要介紹了使用docker部署django技術(shù)棧項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
啟動(dòng)docker錯(cuò)誤systemctl status docker.service問(wèn)題及解決
文章討論了啟動(dòng)Docker和執(zhí)行docker ps命令失敗的問(wèn)題,但docker -v顯示成功,解決辦法包括在阿里云容器鏡像中找到鏡像加速器或使用公共鏡像地址,默認(rèn)情況下,Docker使用官方地址2025-01-01
Docker 部署 Elasticsearch 9 的搭建過(guò)程
本文詳解Elasticsearch 9.x在Linux上通過(guò)Docker部署流程,涵蓋新特性如Lucene10優(yōu)化、BBQ提升向量搜索、EDOT支持多云監(jiān)控等,并指導(dǎo)配置安全認(rèn)證與訪問(wèn)權(quán)限,感興趣的朋友跟隨小編一起看看吧2025-06-06
IDEA直接打包Docker鏡像的實(shí)現(xiàn)
Docker提供了多種方法來(lái)打包鏡像,本文主要介紹了IDEA直接打包Docker鏡像的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06
Idea通過(guò)docker compose?發(fā)布項(xiàng)目的過(guò)程
這篇文章主要介紹了Idea結(jié)合docker-compose發(fā)布項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08
Docker 數(shù)據(jù)管理Named volume詳解
這篇文章主要介紹了Docker 數(shù)據(jù)管理Named volume詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03

