【排坑】云服务器docker部署前后端分离项目+域名解析+OSS

【实战】云服务器docker部署前后端分离项目+域名解析+OSS

踩坑推荐

【大坑!已解决】docker 容器 jar 包连不上另一个容器的 mysql-CSDN 博客

【排坑】程序包 jdk.nashorn.internal.ir.debug 不存在-CSDN 博客

【已解决】 [ org.apache.catalina.core.StandardService : 173 ] - Stopping service [Tomcat]-CSDN 博客

【已解决】redisCache 注解失效,没写 cacheConfig-CSDN 博客

【已解决】OSS 配置问题-CSDN 博客

环境工具

  • 阿里云服务器 Alibaba Cloud Linux 3.2104 LTS 64 位
  • OSS
  • 域名解析(具体就不写了,怕被 DDOS🤡)
  • 后端 jar 包 jdk11、springboot 2.6.13
  • 前端 umimax+antd 系列
  • docker
  • nginx latest
  • redis7.2.4
  • etcd3.5.15
  • mysql8.0.35
  • SSH 客户端 final shell

mysql、redis、nginx 等所有项目依赖环境全部部署在 docker 容器中。 mysql、redis 这些,部署完记得在本地连一下看有没有问题,有问题就用 docker logs 看日志或者进容器改配置,服务器记得放开对应端口 !!

每部署完一个容器就用 docker ps 看一下 status 和 port,如果是 status 是 restarting 或者 port 没映射上,大概率有问题,另外注意 cpu 和内存占用 (final shell 看的很方便),有几次启动容器后 cpu 和内存占用爆满了,服务器都登不上了 🤣

拉取镜像慢的话可以改 docker 镜像配置,具体看

常用 docker 命令

  • docker pull 镜像名    【拉取镜像】
  • docker search  镜像名   【搜索镜像】
  • docker images 【列出 docker 的所有镜像】
  • docker ps(-a) 【列出当前在运行的容器,加上-a 参数列出所有容器,包括停止的】
  • docker stop/start 容器 id 【暂停/开始容器运行】
  • docker rmi 镜像 id 【删除镜像】
  • docker rm(-f)【删除 stop 容器,加上-f 参数可以强制删除 start 容器】
  • docker logs 容器 id 【展示出该容器的运行日志】
  • docker run 【启动镜像,运行一个容器】
  • docker build  【构建镜像】
  • docker info 【查看 docker 版本号等信息】
  • systemctl status docker 【docker 运行信息】
  • docker network 【构建 docker 网络】
  • docker exec -it 容器 id  /bin/bash【进入容器内部】

Docker 部署 mysql

docker pull 拉取 mysql 镜像就不说了,直接运行镜像命令如下

docker run –restart=always  –name blog_mysql --network blog_network  -d  -p 3306:3306  -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=xxxx mysql:8.0.35

解读

  • --restart=always 是每次 docker 服务重启时该容器也自动启动,建议加上,不然每次重启服务器或 docker 时都要手动再启动容器。
  • --name 是给该容器命名,–network 是指定该容器的所属 docker 网络,便于各个容器之间端口通信,
  • -d 是后台运行,
  • -p 是端口映射,我没每次启动一个容器都相当于开启一个新的小操作系统,需要把这个小操作系统的端口和服务器端口做个映射,这样容器才能和外界交流
  • -e 设置环境变量,这里有个坑,如果不指定时区,部署 mysql 后 select now()就会发现mysql 时间和实际时间差 8h,启动时设置下 Asia/Shanghai 即可解决。MYSQL_ROOT_PASSWORD 就是指定 mysql 的连接密码,远程连接要用。
  • mysql:8.0.35 就是指明要运行的镜像。

如果启动后 mysql 远程连接不了,用 docker logs 查看该容器的日志,一般会有提示

Docker 部署 etcd

docker run –restart=always -d –name blog_etcd --network blog_network  -p 2379:2379  –env ALLOW_NONE_AUTHENTICATION=yes   –env   ETCD_ADVERTISE_CLIENT_URLS=http://127.0.0.1:2379   bitnami/etcd:3.5.15

解读:

etcd 以单节点方式启动,设置无需密码,看个人项目是否需要 etcd,不需要就不用部署 etcd

Docker 部署 redis

docker run –restart=always –name blog_redis --network blog_network -p 6379:6379 -v /data/blog_redis/data:/data   -v  /data/blog_redis/conf/redis.conf:/etc/redis/redis.conf  -d redis:7.2.4 redis-server /etc/redis/redis.conf

解读

  • -v 是挂载目录,简单来说就是把服务器的本机目录文件和容器内的某个目录文件做个映射,我把服务器的/data/blog_redis/data 目录映射到了容器内的/data 目录,这个目录用来存 redis 的数据文件,所以需要改 redis.conf 文件中存放数据的配置,我的数据文件存到了/data 下:
  • /data/blog_redis/conf/redis.conf:/etc/redis/redis.conf 就是映射配置文件,redis 启动是需要 conf 文件的,我希望 redis 以我规定的 conf 文件启动,所以要也要挂载一下
  • 有需要的还可以挂载一下日志文件,记得修改 redis.conf

Docker 部署后端

  1. 本地 idea 打 jar 包,然后用 final shell 上传到云服务器,为什么不用阿里的 Workbench 远程连接,因为这个传文件太慢了。坑!打包时记得看控制台的输出日志有没有黄色警告,具体原因看:【已解决】 [ org.apache.catalina.core.StandardService : 173 ] - Stopping service [Tomcat]-CSDN 博客另外打包时记得改 yml 文件的 mysql 和 redis 的 url,ip 地址不要写 127.0.0.1 或 lcoalhost,要写服务器的公网 ip,不然 jar 包连不上 mysql 和 redis,注意 mysql 数据库大小写具体看这个:【大坑!已解决】docker 容器 jar 包连不上另一个容器的 mysql-CSDN 博客
    yml 文件写的数据库是 Blog,实际数据库是 blog
  2. 在 jar 包的同一目录下,创建一个 blog_dockerfile 文件,内容如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM openjdk:11-jre-slim

RUN apt-get update && apt-get install -y bash && rm -rf /var/lib/apt/lists/*

COPY blog-0.0.1-SNAPSHOT.jar /app/

WORKDIR /app

EXPOSE 8081

CMD [“bash”, “-c”, “java -jar -Duser.timezone=GMT+08 blog-0.0.1-SNAPSHOT.jar “]

解读

  • FROM openjdk:11-jre-slim  是下载 jar 包运行需要的 jdk,我只需要 jar 运行环境,所以下了 jre,slim 是基于 Debian/Ubuntu,而 alpine 是基于 centos 的,操作系统倒无所谓,我用两个都部署了 jar 包都能成功。这里我发现 jdk11 要比 jdk8 的镜像包大很多,而且用 jdk11 docker build 的时候特别慢,甚至会构建失败,用 jdk8 就特别快 2. COPY 把当前目录(dockerfile 所在目录)的 jar 包拷贝到容器的/app/目录下 3. WORKDIR 设置工作目录为/app/ 4. EXPOSE 暴露 8081 端口,因为我的 jar 包运行在 8081 端口。他需要和外界通信,所以得暴露出来 5. CMD 就是用 docker run 启动容器后他要执行的命令了,这里有个坑 -Duser.timezone=GMT+08,启动时指定了时区,不指定的话会发现 jar 包的运行日志时间和实际时间差 8h

  • docker build -f blog_dockerfile -t blog-backend .
    写好 dockerfile 后构建镜像,-f 是指定 dockerfile 文件,-t 是构建镜像后的镜像名,.就是当前目录

  • docker run –name blog-backend -d –restart=always  -v /data/blog_backend/logs:/tmp/logs  --network blog_network  -p 8081:8081  blog-backend:latest
    构建完镜像后启动,这里我挂载了日志文件,方便查看日志,如果不挂载的话每次看日志都得进到容器里面,不方便,而且只有容器运行的时候才能进容器内部,如果容器停了就进不去,-p 映射端口,我后端部署在 8081,这里和服务器的 8081 端口做了个映射。

Docker 部署前端

  • 本地 vscode 构建,生成的 dist 目录用 final shell 上传到云服务器,同样在 dist 同一目录下建一个 blog_fronted_dockerfile 文件,内容如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
FROM nginx

RUN rm /etc/nginx/conf.d/default.conf
ADD default.conf /etc/nginx/conf.d/

EXPOSE 80

EXPOSE 443

COPY dist/  /usr/share/nginx/html/

CMD [“nginx”, “-g”, “daemon off;]
然后还需要一个 default.conf 来替换 nginx 的默认配置文件,内容如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {

listen       80;#nginx 默认监听 80 端口,可以改成其他的
    server_name  公网 ip;
    #server_name  域名;如果有域名,解析后可以用域名,不用 ip

location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html =404;
    }

# 后端接口转发

location /api/ {
        proxy_pass http://公网 ip:8081;  # 转发到后端服务 8081 端口
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}
  • docker build -f blog_fronted_dockerfile -t blog-fronted .
    构建镜像
  • docker run –restart=always -d -p 443:443 -p 80:80  –name blog_fronted blog-fronted:latest
    运行镜像,映射 443 和 80 端口

OSS 配置

看我这篇文章

【已解决】OSS 配置问题-CSDN 博客

防盗链设置

我们存储在 oss 的图片通过图片 url 来访问,如果有其他用户拿到了我们的图片 url 进行访问就会刷我们的流量甚至欠费,所以最好设置防盗链,白名单加上前端部署的域名即可

加上防盗链之后我们测试一下,拿着图片 url 在本地浏览器访问,结果如下,因为白名单仅对服务器开放了权限,没有对本地开放,所以本地访问就无权限了

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计