微同商城docker部署指南

姬广超2022年10月25日
  • 商业版
  • 指南
  • docker
大约 12 分钟

微同商城docker部署指南

概述

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

1. 云服务器安装docker

通过ssh登陆云服务器,推荐终端神器mobaxtermopen in new window(谁用谁说好)。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. 修改微同商城的生产环境配置,并进行打包

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

7.1. 修改platform-admin模块的application.yml和application-prod.yml

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

server:
  port: 8088 # 原先为8888我改成了8088
redis:
    database: 0
#    host: 127.0.0.1
    host: redis 
    port: 6379
    # 密码(默认为空)
    password:
    # 连接超时时长(毫秒)
    timeout: 6000ms

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

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    dynamic:
      primary: master # 设置默认的数据源或者数据源组,默认值即为 master
      datasource:
        master:
          url: jdbc:mysql://mysql:3306/platform-plus?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          driverClassName: com.mysql.cj.jdbc.Driver
        second:
          url: jdbc:mysql://mysql:3306/platform-plus?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          driverClassName: com.mysql.cj.jdbc.Driver

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

7.2. 修改platform-api模块的application.yml和application-prod.yml

过程和7.2的一样,修改两个配置文件的同样位置。但是在application.yml文件中我进行了端口修改:server: port: 8089

7.3. 打包

在项目根目录执行下面命令: mvn package -Pprod 等待打包完成,找到platform-admin.jarplatform-api.jar这两个文件。

8. 编写两个dockerfile文件生成两个镜像

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

mkdir ~/mall-docker

platform-admin.jarplatform-api.jar这两个文件上传到云服务的这个目录,然后分别编写platform-admin-dockfileplatform-api-dockfile文件。

FROM openjdk:8
ADD platform-admin.jar platform-admin.jar
CMD	java -jar platform-admin.jar
EXPOSE 8088
FROM openjdk:8
MAINTAINER tonygee <253106788@qq.com>
ADD platform-api.jar platform-api.jar
CMD	java -jar platform-api.jar
EXPOSE 8089

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

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

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

version: "3"
services:
  nginx:
    image: nginx
    container_name: c_nginx
    ports:
      - 80:80
      - 8012:8012
      # - 8088:8088
      # - 8089:8089
    # links:
    #   - mall_app
    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-admin
      - mall-api
  mall-admin:
    image:  mall-admin-img
    build:
      context: ./
      dockerfile: platform-admin-dockfile
    container_name: c_mall_admin
    ports:
      - "8088:8088"
    # volumes:
    #   - ~/mall_app/app/data:/data
    networks:
      - mall_app_net
    depends_on:
      - redis
      - mysql
  mall-api:
    image:  mall-api-img
    build:
      context: ./
      dockerfile: platform-api-dockfile
    container_name: c_mall_api
    ports:
      - "8089:8089"
    # volumes:
    #   - ~/mall_app/app/data:/data
    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
├── platform-admin-dockfile
├── platform-admin.jar
├── platform-api-dockfile
└── platform-api.jar

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

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环境下执行下面命令:

create database `platform-plus`;
use platform-plus;
source /etc/mysql/conf.d/platform-mall-MySQL.sql;
source /etc/mysql/conf.d/platform-mall-MySQL.sql-activiti.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 /platform-admin {
      proxy_pass  http://mall-admin: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;
    }

    location /platform-api {
      proxy_pass  http://mall-api:8089;
      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-admin:8088一定不要写成proxy_pass http://mall_admin:8088,否则nginx代理的时候会出错!这也是在“9 编写docker-compose文件启动所有服务 ”步骤中定义服务名称千万不要用下划线的原因!还是那句话,说多了都是泪。

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

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

vscode打开platform-admin-ui文件夹,然后进行下面的操作: 修改文件:

/static/config/index-prod.js文件
window.SITE_CONFIG['baseUrl'] = 'http://你的域名/platform-admin' // 后台接口请求地址
//如果使用第三方文件存储,将dist/1907180922 上传至第三方文件存储,然后填写cdn地址
window.SITE_CONFIG['domain'] = '静态资源cdn地址';

执行命令:

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

先备份一下~/mall_app/nginx/html目录里面原有的文件,然后把platform-admin-ui->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部署基本完成!

13. 服务测试

  • 浏览器输入:http://"你的域名或者ip"/platform-api/doc.html访问swagger文档
  • 浏览器输入:http://"你的域名或者ip"访问管理后台首页。默认用户名 admin,密码:888888。

学习资料参考