使用docker进行前后端分离的微服务项目部署上线

对于我们个人开发者而言,开发完一个项目之后,总会有一个问题就是这个项目要不要部署上线。本次就使用docker将我开发好的一个前后端分离的微服务项目部署上线。

本次部署项目用到了宝塔面板来进行实时的监控,如果你没有安装宝塔面板,可以参考一下这篇文章。

购买服务器,并安装宝塔_宝塔购买-CSDN博客

注意宝塔面板的放行,下载完宝塔之后,我们直接使用可视化页面进行项目的部署。

点击docker,直接使用可视化页面的方式进行下载。

下载完docker之后,进行docker加速镜像的配置;

如果不存在/etc/docker/daemon.json这个配置文件,可以直接使用下面的命令:

# 创建目录
sudo mkdir -p /etc/docker
# 写入镜像配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
        "https://docker.m.daocloud.io",
        "https://dockerproxy.com",
        "https://docker.mirrors.ustc.edu.cn",
        "https://docker.nju.edu.cn"
    ]
}
EOF
# 重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker

如果已经存在/etc/docker/daemon.json这个配置文件,手动复制下面的镜像地址加如到配置中:

"registry-mirrors": [
        "https://docker.m.daocloud.io",
        "https://dockerproxy.com",
        "https://docker.mirrors.ustc.edu.cn",
        "https://docker.nju.edu.cn"
    ]

配置完成之后,别忘了一定要重启Docker服务:

# 重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker

现在,我们已经可以开始进行docker容器化的部署了。

我们首先要明确我们需要那些容器,大致可以分为两类。

一类是环境容器,如:MySQL、redis、nginx、nacos、minio等等

一类是业务容器,如:gateway模块、user模块、product模块等等。

由于我们的业务容器要依赖于环境容器才能够进行正常的启动,所以,我们正常情况下都是先进行环境容器的搭建。

环境容器的搭建:

首先我们要先明确我们的项目用到了那些的环境依赖,我的这一个电商项目部署用到了

nginx、MySQL8.0.30、redis7.0.10、minio、nacos2.2.2

首先拉取相应的docker镜像:

docker pull nginx 
docker pull mysql:8.0.30
docker pull redis:7.0.10
docker pull quay.io/minio/minio
docker pull nacos/nacos-server:v2.2.2-slim

全部拉取下来之后,就可以直接在宝塔的控制台页面查看到自己的本地镜像。

现在有了镜像之后,我们就可以根据这些镜像来进行容器的搭建;

要特别注意的一点是:Docker默认的网络模式(bridge模式)下,并不直接支持通过默认的容器名称来相互访问。所以,我们要想这些容器能够通过容器名称来进行相互的访问,我们必须要新建一个网络,并将所有的容器放在这个网络下面。

创建一个docker网络:

docker network create zhangqiao-network

nginx容器创建

docker run -d -p 80:80 \
-v /usr/zhangqiao/nginx/dist:/usr/share/nginx/html \
-v /usr/zhangqiao/nginx/config/nginx.conf:/etc/nginx/nginx.conf \
--network zhangqiao-network \
--name nginx \
nginx

docker run:根据镜像启动容器,如果没有镜像会先下载镜像,再启动容器

  • -d:后台运行
  • -p:服务器暴露端口:容器端口
  • -v:目录挂载【可以配置多个】
    • /usr/zhangqiao/nginx/dist:物理机的目录
    • /usr/share/nginx/html:容器中的目录
  • --name:给这个容器起个名字
  • nginx:获取镜像的名字,不写版本号,默认是least

nginx.conf的配置文件内容为:


#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  60.204.174.35;
        charset utf-8;

        location / {
            root   /usr/share/nginx/html; # 需要和服务器项目所在地址进行挂载
            try_files $uri $uri/ /index.html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

现在只是一个非常简单的nginx配置,我们后期还要进行改动。

注意挂载目录的时候,如果是文件夹挂载。那么如果文件夹不存在时,创建容器时会自动创建目录;如果是文件挂载:如nginx.cong,那么一定要存在这个文件,不然会报错。显示挂载的文件类型不一致(原因是自动将文件创建成了文件夹的形式)

我们nginx容器创建完成之后,一定要注意端口的放行。我们要将80端口放行出去让所有的地址都可以访问到。在安全组中进行端口的放行。

现在,我们访问一下nginx服务;

可以正常访问到nginx,现在只是因为我们的前端项目没有部署到dist目录下,所以现在nginx什么都访问不到。但是是能够正常运行的;

MySQL容器创建

docker run -d -p 3388:3306 \
-v /usr/zhangqiao/mysql/conf:/etc/mysql/conf.d \
-v /usr/zhangqiao/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=自己设置的MySQL密码 \
--network zhangqiao-network \
--name mysql \
mysql:8.0.30

关于MySQL要特别强调的一点是,MySQL的端口不要暴露出去,另外端口号和密码也不要设置的过于简单,这样很容易遭到攻击。我们到时候将这些容器放在同一个docker的网关之下就可以正常的进行容器之间的相互调用了。

MySQL的端口不要暴露出去

MySQL的端口不要暴露出去

MySQL的端口不要暴露出去

重要的事情说三遍,如果你要进行数据库的导入。可以在项目中使用flyway数据库版本工具进行SQL语句的执行,或者短暂的暴露执行完SQL之后(几分钟)一定要重新的将端口关闭,我曾经将MySQL的端口暴露之后也就短短几天的工夫,数据全部被人清掉了,还留下了威胁的语句要给某个账户打钱才能恢复数据,我们遇到这种情况一定不要妥协,因为大概率你打完钱之后也不会给你回复数据。

这张图就是我的MySQL数据库被攻击的样子,我想说的是,一定不要将你的数据这种敏感的东西直接暴露到网上。

redis容器创建

docker run -d -p 6380:6379 --name redis \
-v /usr/zhangqiao/redis/data:/data \
-e REDIS_PASSWORD=zhangqiao24 \
--network zhangqiao-network \
redis:7.0.10 redis-server --requirepass zhangqiao24  --appendonly yes

配置一下redis的配置文件,也就是放开了redis的访问权限;

bind 0.0.0.0
protected-mode no
port 6380
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
always-show-logo no
set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /usr/zhangqiao/redis/data
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-diskless-sync-max-replicas 0
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass zhangqiao24@!/
maxclients 10000
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
lazyfree-lazy-user-flush no
oom-score-adj no
oom-score-adj-values 0 200 800
disable-thp yes
appendonly yes
appendfilename "appendonly.aof"
appenddirname "appendonlydir"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
aof-timestamp-enabled no
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-listpack-entries 512
hash-max-listpack-value 64
list-max-listpack-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-listpack-entries 128
zset-max-listpack-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

我这边redis的话,是单机启动redis。如果你想要进行主从、集群等功能。可以自己再进行redis容器的配置

minio容器创建

docker run \
   -p 9001:9000 \
   -p 9090:9090 \
   --name minio \
   -v /usr/zhangqiao/minio/data:/data \
   -e "MINIO_ROOT_USER=用户名" \
   -e "MINIO_ROOT_PASSWORD=密码" \
   --network zhangqiao-network \
   -d \
   quay.io/minio/minio server /data --console-address ":9090"
                        

对于minio,我们可能还是要进行外部访问,所以可以将端口的权限放开

直接访问9090端口。

nacos容器创建

要注意的是,nacos容器的运行是非常占用内存的。所以,我本次拉取的镜像版本是nacos/nacos-server:v2.2.2-slim 如果你的服务器运行内存大的话,可以选择去掉后面的-slim版本。如果运行内容没有那么大的话,还要在创建nacos容器时指定一下nacos的最大运行内容,防止nacos占用的内容过大。

docker run \  
-e JVM_XMS=128m \
-e JVM_XMX=128m  \
-e MODE=standalone \
--network zhangqiao-network \
-p 8848:8848 \
-p 9848:9848 \
--name nacos \
-d \
nacos/nacos-server:v2.2.2-slim

我这边的话,是单机启动nacos。

如果你需要部署nacos集群的话,可以在创建容器的时候,挂载一个nacos的配置文件。

业务容器的搭建

打包前端项目

直接运行打包命令将前端的vue3项目打出静态的文件夹。

npm run build 或者
yarn run build

dist文件夹就是我们打好的前端资源包,可以直接将这个资源包放在之前我们配置nginx的路径下;

现在,我们就得到了一个存静态的HTML页面了。再次访问我们的nginx容器;

注意,将前端项目打出静态包时,要保证我们的项目路径都已经正常的改成我们的服务器地址了。

打包后端项目

我的后端项目是一个微服务项目,我们只需要在父模块下直接运行打包命令就可以了。

对与每个子模块都写一个上线的配置application-prod。在这个上线配置中,我们之前的一些环境都是写的本地的,我们现在要将它们改为我们线上的容器名称:

将所有的模块的配置文件都写完之后,就可以将子模块都打成jar包了(在这里提醒一点,我们打jar包的时候,一定是要将所有的问题都解决之后,才可以打包部署到线上。)

现在,我们直接在父项目下执行完命令之后就可以直接将所有的子模块全部都打到jar包,并将我们打成的jar包上传到服务器上,并最终制作成容器。有一点要注意的是,我们的容器注意要放在同一个docker的网络中,这样才能够进行容器之间的相互访问。

新建一个文件夹sa-gateway,将我们打好的jar包上传到这个文件夹中;

在这个文件夹下再新建一个Dockerfile文件,并在这个文件中来进行我们的配置;

FROM openjdk
 
COPY sa-gateway-1.0-SNAPSHOT.jar /app/app.jar
 
CMD ["java", "-jar", "/app/app.jar"]

就三句代码就可以,现在来简单的解释一下这三句代码;

FROM openjdk:这一行指定了基础镜像,即从哪个镜像作为基础进行构建。在这里使用了 openjdk 镜像,表示基于 OpenJDK 的镜像作为基础。(因为是Java项目,所以在运行时要有相应的环境才行)

openjdk,是我docker中的一个镜像。是jdk17的镜像;

如果你的docker中没有这个镜像是会报错的;可以下载一个镜像(也可以是其他的jdk版本,都可以,甚至是jre都行,毕竟我们只是要运行Java项目)

docker pull openjdk:17

COPY sa-gateway-1.0-SNAPSHOT.jar /app/app.jar:

这一行的作用是将本地的 sa-gateway-1.0-SNAPSHOT.jar 文件复制到容器内的 /app/app.jar 路径下。

COPY 指令的语法为 COPY <源路径> <目标路径>,它将本地文件或目录复制到容器中的指定路径。(这里因为sa-gateway-1.0-SNAPSHOT.jar与Dockerfile文件在同一个文件夹下,我才这么写的,也可以不在同一个文件夹下,用相对路径和绝对路径来指明位置)

CMD ["java", "-jar", "/app/app.jar"]:

这一行定义了容器启动时要执行的默认命令。在这里,使用 java -jar /app/app.jar 命令来启动  应用程序。

CMD 指令用于指定容器启动时要运行的命令,可以有多种格式,包括字符串格式和数组格式。在这里使用的是数组格式。

接下来还是在这个文件夹下来使用docker创建镜像;

docker build -t sa-gateway  .

 这是用来构建 Docker 镜像的命令:

docker build: 这是 Docker 命令行工具的一个子命令,用于构建 Docker 镜像。

-t sa-gateway: -t 参数用来给构建的镜像指定一个标签(tag)。在这里,将构建的镜像命名为 sa-gateway。

.: 这表示构建镜像所需的上下文路径。Docker 将在当前目录中查找 Dockerfile 文件以用于构建镜像。

综合起来,这条命令的作用是在当前目录中查找名为 Dockerfile 的文件,并使用该 Dockerfile 文件构建一个名为 sa-gateway 的 Docker 镜像。

注意最后这个 .  很重要,它表示在当前目录中查找,如果你的文件不在当前目录,也可以用绝对或相对路径来指明;

现在,我们已经构建成功了这个镜像,可以在我们的本地镜像里查看;

创建docker镜像;

 docker run -d --name sa-gateway   --network zhangqiao-network      -p 8500:5800 sa-gateway

运行这个命令就可以成功的构建出一个运行中的容器;

要查看我们这个容器有没有运行起来,可以在nacos中进行查看,由于我们的网关gateway放在了nacos中,所以如果启动成功的话。那么我们的nacos中应该是能看到我么们的网关服务的。

能够看到我们的网关服务,那么说明我们的容器已经启动起来,并且容器之间是能够相互进行访问的。(如果你的nacos中不能看到网关服务,检查一下你的这些容器是否在同一个docker网络中)

这只是一个网关的子模块,接下来就可以按照网关的容器的制作形式将所有的子模块全部制作成可以访问的容器。

我这边有六个子模块加上五个环境依赖,一共是11个容器。这边的服务器是2核4G的服务器,能够支持的起这11个容器,如果你觉得你的服务器内存不够的话,可以在制作业务容器时,制定一下容器的最大占用内存:

-e JVM_XMS=128m \
-e JVM_XMX=128m  \

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张乔24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值