spring boot 项目 docker 部署指南

spring boot项目docker部署指南

概述

通过docker部署应用和微服务是目前的主流,本教程根据作者部署项目的亲身实践进行编写。如果您初次接触docker,可能会觉得这样部署比较麻烦,因为需要了解container(容器)、image(镜像)、dockerfile、docker-compose等概念。可以先放下这些概念,直接按本教程的描述进行部署。通过体验之后,会发docker部署应用的好处很多,再进行docker系统的学习。
注意:本教程是基于albaba cloud linux 3 云服务器环境,centos7 通用。

1 云服务器安装docker

通过ssh登陆云服务器,推荐终端神器mobaxterm(谁用谁说好)。shell环境直接输入下面的命令进行安装:

# 1、yum 包更新到最新 
yum update
# 2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 
yum install -y yum-utils device-mapper-persistent-data lvm2
# 3、 设置yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 4、 安装docker,出现输入的界面都按 y 
yum install -y docker-ce
# 5、 查看docker版本,验证是否验证成功
docker -v

2 启动docker服务,并设置开机启动

直接复制,shell环境直接输入下面的命令:

 systemctl start docker
 systemctl enable docker

3 docker镜像加速设置(本步骤可以省略!)

注册一个属于自己的阿里云账户(可复用淘宝账号),用支付宝扫码登陆阿里云。找到“容器镜像服务”->“镜像工具”->“镜像加速器”,然后看到自己独立的镜像加速地址和centos操作文档。根据操作文档,复制到shell进行粘贴就行。

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://'你自己的加速地址,不要直接复制'.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

4 使用docker拉取nginx、Redis、mysql镜像

直接复制,shell环境直接输入下面的命令:

docker pull mysql:5.7     # 5.7 是指定版本号
docker pull redis:5.0     # 5.0 是指定版本号
docker pull nginx         # 这里没写版本号,意思是拉取最新的版本
docker images             # 查看本机所有镜像

5 使用docker相关命令操作container(本步骤可以省略!主要是熟悉一下container的相关操作)

5.1 使用docker run命令命令建立并运行container

由于我们已经获取了mysql的镜像,可以用docker run命令启动一下服务进行初步的体验。补充一下概念,可以把image(镜像)类比为java的类文件,container(容器)理解为对象,而docker run命令为new关键字。每一个container(容器)都是一个微小的虚拟机,有自己的网络地址和端口。这里以nginx和mysql为例。shell环境直接输入下面的命令:

### 运行nginx
docker run --name c_nginx -p 80:80 -d nginx  #用nginx镜像启动名字为 c_nginx 容器实例后台运行(-d),并且把本机(宿主机)的80端口(-p)映射到c_nginx容器的80端口
### 下面来个稍微复杂点的
docker run -d \ 
-p 3306:3306 \
--name=c_mysql \
-v ~/mysql/conf:/etc/mysql/conf.d \  
-v ~/mysql/logs:/logs \            
-v ~/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \     
--privileged=true mysql:5.7       

上面复杂命令的解释:
docker run -d \
-p 3306:3306
–name=c_mysql
-~/mysql/conf:/etc/mysql/conf.d \ # 这里的 -v 意思是挂载(共享)宿主机的 ~/mysql/conf 文件夹作为c_mysql容器的/etc/mysql/conf.d
-~/mysql/logs:/logs \ # 用以实现文件同步和保存。因为容器如果被删除掉,宿主机还保存着相应的数据
-v ~/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 \ # 设置root密码
–privileged=true mysql:5.7 # --privileged=true 设置容器的文件权限。注意这里的镜像mysql:5.7和拉取的镜像一致,使用了版本号。

可以通过docker COMMAND --help命令自行学习,例如:docker run --help

5.2 使用docker exec命令命令进入container

     docker exec -it c_nginx /bin/bash # 进入刚才建立的c_nginx容器
     docker exec -it c_mysql /bin/bash # 进入刚才建立的c_mysql容器

可以通过docker exec --help自行了解-it的参数作用。

5.3 其它常用docker操作container的命令

     docker ps -a            # 查看所有容器。-a 意思是包括已经停止的容器。
     docker stop    c_nginx  # 停止c_nginx容器
     docker start   c_nginx  # 运行c_nginx容器
     docker restart c_nginx  # 重新运行c_nginx容器
     docker logs 4358e2ad63d5  # 4358e2ad63d5 为 c_nginx容器的id。docker ps 命令可以看到。
     docker inspect 4358e2ad63d5 # 查看容器的详细信息 
     docker cp c_nginx:/etc/nginx/ ~/nginx/conf/ # 从c_nginx容器里面复制文件到宿主机

6 准备 nginx container 的运行环境

nginx需要特别对待一下。这个步骤的主要目的是从一个临时容器里面获取nginx的配置文件。

    mkdir ~/mall-app/nginx -p
    # 1. 先建立一个临时nginx容器
    docker run --name c_nginx -p 80:80 -d nginx
    # 2.
    #复制临时nginx容器的文件到主机
    docker cp c_nginx:/etc/nginx/ ~/mall-app/nginx/conf/
    docker cp c_nginx:/usr/share/nginx/html/ ~/mall-app/nginx/html/
    docker cp c_nginx:/var/log/nginx/ ~/mall-app/nginx/logs
    # 3.
    docker rm -f "nginx容器id"   # docker ps 命令可以得到nginx容器id

这样操作之后就在~/mall-app/nginx文件夹里面保存了一个完整的nginx服务相关的文件。为什么多此一举?因为在接下来通过docker-compse批量启动容器的时候,会把nginx container的/etc/nginx目录挂载为宿主机的~/mall-app/nginx/conf。这时如果宿主机的~/mall-app/nginx/conf文件夹是空的,会覆盖掉c_nginx:/etc/nginx,造成nginx 容器启动失败。当然也有其它解决办法,个人比较喜欢这样做。

7 修改boot程序的环境配置,并进行打包

由于在docker环境下boot jar包nginxmysqlRedis都是以微服务的方式运行(就是在独立的container里面运行),每个container有独立的ip地址,并且不是固定的,因此在相应的配置文件中用到ip地址的地方就要改成服务名称!这点非常重要!

7.1 修改mall-app模块的application.yml

application.yml文件按照下面进行修改:

server:
  port: 8088

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://mysql:3306/mall-app?serverTimezone=UTC
    username: root
    password: jn@run@2022
    type: com.alibaba.druid.pool.DruidDataSource
redis:
    database: 0
#    host: 127.0.0.1
    host: redis 
    port: 6379
    # 密码(默认为空)
    password:
    # 连接超时时长(毫秒)
    timeout: 6000ms

这样修改之后,原来配置文件中的localhost或者127.0.0.1就改成了服务名称mysqlredis。为什么是这个两个指定的名称?因为在后面的步骤的编写docker-compose文件时候会对服务名称mysqlredis进行定义。

7.2 通过idea的maven进行打包

直接点击idea maven 功能区的 package 按钮,等待打包完成,找到mall-app-0.0.1-SNAPSHOT.jar这个文件。

8 编写dockerfile文件生成镜像

通过dockerfile可以自定义镜像。在第上面使用docker拉取nginxRedismysql的步骤中,拉取的镜像都是官方已有的。想要定义自己的微服务镜像,就需要先编写dockerfile
先建立一个工作目录:

mkdir ~/mall-docker

mall-app-0.0.1-SNAPSHOT.jar这个文件上传到云服务的这个目录,然后编写mall-app-dockfile文件。

FROM openjdk:11
ADD mall-app-0.0.1-SNAPSHOT.jar mall-app.jar
CMD	java -jar mall-app.jar
EXPOSE 8088

编写完dockerfile就可以在当前文件夹下用命令docker build -f ./mall-app-dockfile -t mall-app-img .生成自定义镜像了。这里我们直接跳过这一步,因为可以在下面的docker-compose文件中直接用脚本生成镜像,并直接运行容器。

9 编写docker-compose文件启动所有服务

9.1 安装docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

9.2 编写docker-compose文件

本教程的核心就是下面这个docker-compose.yml文件!在~/mall-docker的目录下新建docker-compose.yml文件,并把下面的代码复制并保存。注意,这里文件名必须为docker-compose.yml。还需注意的是在下面的配置中我们定义了一个个服务mall-app千万不要使用下划线这样定义为mall_app。这里有个很大的坑一会再说!

version: "3"
services:
  nginx:
    image: nginx
    container_name: c_nginx
    ports:
      - 80:80
    volumes:
      - ~/mall-app/nginx/conf/:/etc/nginx/
      - ~/mall-app/nginx/html/:/usr/share/nginx/html/
      - ~/mall-app/nginx/logs:/var/log/nginx/
    networks:
      - mall-app_net
    depends_on:
      - mall-app
  mall-app:
    image:  mall-app-img
    build:
      context: ./
      dockerfile: mall-app-dockfile
    container_name: c_mall_app
    ports:
      - "8088:8088"
    networks:
      - mall-app_net
    depends_on:
      - redis
      - mysql
  redis:
    image: redis:5.0
    container_name: c_redis_app
    ports:
      - "6379:6379"
    volumes:
      - ~/mall-app/redis/redis.conf:/etc/redis/redis.conf
      - ~/mall-app/redis/data:/data
    networks:
      - mall-app_net
    command: redis-server /etc/redis/redis.conf
  mysql:
    image: mysql:5.7
    container_name: c_mysql_5_7_app
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
    ports:
      - "3306:3306"
    volumes:
      - ~/mall-app/mysql/data:/var/lib/mysql
      - ~/mall-app/mysql/conf:/etc/mysql/conf.d
      - ~/mall-app/mysql/logs:/logs
    networks:
      - mall-app_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
networks:
  mall-app_net:

这时~/mall-docker的目录结构如下:

~/mall-docker
├── docker-compose.yml
├── mall-app-dockfile
└── mall-app.jar

最后cd ~/mall-docker目录,执行docker-compose up -d,观察控制台输出的日志。如果没有什么问题,使用docker ps -a看一下相4个服务是否启动。

10 设置mysql配置文件,并导入sql脚本生成数据库数据

先编写一下mysql的配置文件。由于在上面的docker-compose.yml文件中定义mysql服务的时候有这一行- ~/mall-app/mysql/conf:/etc/mysql/conf.d,我们只需输入下面命令即可:

cd ~/mall-app/mysql/conf
vi my.cnf  # 把下面的配置复制过来就行
[client]
default_character_set=utf8
host     = localhost
user     = root
password = 123456
#database = test
[mysqld]
character_set_server=utf8
collation_server=utf8_general_ci
#port = 3306
[mysql]
default_character_set=utf8
docker restart 7f13f2cf0821  # 7f13f2cf0821为mysql容器的id。docker ps 命令可以看到。
# docker logs 7f13f2cf0821   # 如果启动失败,通过该命令查看日志  

注意:这里的文件名为my.cnf,不要写成my.ini;里面的类似default_character_set=utf8的配置不要写成default-character-set=utf8,都是踩过的坑和教训,说多了都是泪!
然后通过sftp把微同商城的两个sql脚本platform-mall-MySQL.sqlplatform-mall-MySQL.sql-activiti.sql也上传到~/mall-app/mysql/conf目录。继续输入命令:

docker exec -it 7f13f2cf0821 /bin/bash

进入mysql容器后,输入mysql直接进入数据库的shell。为什么不需要用mysql -uroot -p输入密码?因为我们在刚才的my.cnf中已经进行了配置。
然后在mysql的shell环境下执行下面命令:

mysql> create database mall-app;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-plus' at line 1

然后你得到上面的报错,自己开始怀疑人生了。恭喜,又入坑了!不要慌,使用mall-app加上反单引号就可以了,别问我怎么知道的,都是泪。

create database `mall-app`;
use mall-app;
source /etc/mysql/conf.d/mall-app-MySQL.sql;

11 编写nginx的配置文件,进行端口映射

同样由于在上面的docker-compose.yml文件中定义nginx服务的时候有这一行- ~/mall-app/nginx/conf/:/etc/nginx/
我们只需在宿主机上面:

cd ~/mall-app/nginx/conf/conf.d/
mv default.conf default.conf_bak
vim  mall.conf

把下面的配置内容保存到mall.conf:

server {
    listen  80;
    #server_name  localhost;

    location / {
      root /usr/share/nginx/html;
      index index.html;
    }

    location /mall-app {
      proxy_pass  http://mall-app:8088;
      proxy_set_header  Host $host;
      proxy_set_header  X-Real-IP $remote_addr;
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

然后用docker restart "nginx容器的id" 命令重启服务,并用curl根据情况进行测试。因为在写本教程的时候,域名还没申请好所以在上面的配置中还没有进行域名的相关配置。特别需要注意的是proxy_pass http://mall-app:8088一定不要写成proxy_pass http://mall_app:8088,否则nginx代理的时候会出错!这也是在“9 编写docker-compose文件启动所有服务 ”步骤中定义服务名称千万不要用下划线的原因!还是那句话,说多了都是泪。

docker restart e7acb5e9aec8 
curl localhost    # 现在还没部署管理后台的前端,这里现在应该是打印nginx主页的信息
curl curl localhost/mall-app/doc.html   # 正常应该打印微同商城swagger首页的html代码

12 打包前端,静态部署到nginx

vscode打开mall-app文件夹,然后进行下面的操作:
执行命令:

npm install
# 构建生产环境
npm run build

先备份一下~/mall-app/nginx/html目录里面原有的文件,然后把mall-app->dist目录下的所有文件上传到~/mall-app/nginx/html~/mall-app/nginx/html目录最终为下面这个样子:

[root@iZuf63zu4bo54nzzdqs9akZ html]# ls
2210241102  50x.html_bak  config  index.html  index.html_bak

进行测试,看一下是否能访问管理后台的页面

curl localhost    # 这里现在应该是打印”微同软件管理平台”信息

docker部署boot微服务安装基本完成!

13 重新上传jar包注意的问题

重新打包并上传jar的时候需要:注意必须先执行docker-compse build,再执行docker-compse up -d。否则docker-compse不会使用新的jar包建立镜像!

学习资料参考:

  • docker官网:http://www.docker.com
  • Docker Hub官网: https://hub.docker.com/
  • 【尚硅谷2022版Docker实战教程(docker教程天花板)】 https://www.bilibili.com/video/BV1gr4y1U7CY?p=75&share_source=copy_web&vd_source=d9ce631f6c235cba374ea8d94b3b4606
  • 作者:姬广超,微信:newchoose,个人网站:www.jiguangchao.com(网站已经停了,过段时间进行部署)

你可能感兴趣的:(docker,docker,容器,运维,spring,boot)