工程化Docker最佳实践之docker-compose部署前后端项目!

2,453 阅读4分钟

docker-compose 安装

虽然已经安装过docker了,但是还得单独安装一下docker-compose,执行以下命令直接安装。

$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

配置大全

可以作为参考了解一下

    # 第一部分: Building(构建镜像)
     web:
       # 使用当前目录下的Dockerfile
       build: .
       args: # 增加额外参数
         APP_HOME: app
       volumes: # 目录挂载,宿主机在前,容器在后
         - .:/code
       depends_on: # 依赖db和redis
         - db
         - redis
     
       # 使用定制化的Dockerfile,指定新目录相对路径和文件名
       build:
         context: ./dir 
         dockerfile: Dockerfile.dev
         container_name: app # 自定义容器名
     
       # 基于现有镜像构建
       image: ubuntu
       image: ubuntu:14.04
       image: remote-registry:4000/postgresql
       image: bcbc65fd
     
     # 第二部分: Ports(端口)
       ports: # 指定端口映射,HOST:Container
         - "6379" # 指定容器的端口6379,宿主机会随机映射端口
         - "8080:80"  # 宿主机端口8080,对应容器80
     
       # 暴露端口给-link或处于同一网络的容器,不暴露给宿主机。
       expose: ["3000"]

     # 第三部分: Environment Variables(环境变量)
       environment:
         MODE: development
         SHOW: 'true'
     
       # 等同于
       environment:
         - MODE=development
         - SHOW: 'true'     
     
       # 使用环境变量.env文件
       env_file: .env
       env_file:
         - ./common.env
         - ./apps/web.env
     
     # 第四部分:commands (命令)
       # 容器启动后默认执行命令,会被docker run覆盖
       command: bundle exec thin -p 3000
       command: ['/bin/bash/', 'start.sh']
     
       # 容器启动后程序入口
       entrypoint: /code/entrypoint.sh
     
     # 第五部分:Networks(网络)
       networks: # 使用bridge驱动创建名为frontend的网络
         frontend:
           driver: bridge
     
         networks: # 使用创建的网络进行通信
           - frontend
     
         # 加入已经存在的外部网络
         networks: 
           default:
             external:
               name: my-pre-existing-network
     
     # 第六部分:Volumes(数据卷)
       volumes: # 创建名为postgres_data的数据卷
            - /data/mysql/data:/var/lib/mysql
     
     # 第七部分:External Links(外部链接)
     # 目的是让Compose能够连接那些不在docker-compose.yml中定义的单独运行容器
       services:
         web:
           external_links:
             - redis_1
             - project_db_1:mysql

常用命令

下面是一些我认为很常用的docker-compose命令

 # 构建文件内的镜像,重新构建服务的镜像,但不会创建和启动容器
 $ docker-compose build				
 
 # 构建镜像并启动容器
 $ docker-compose up
 # 后台创建并启动容器
 $ docker-compose up -d 							
 # 指定文件内某一个容器(java)构建镜像并启动容器
 $ docker-compose up java								
 # 指定文件内某一个容器(java)后台构建镜像并启动容器,-d 放前面
 $ docker-compose up -d java 							
 # 启动指定yml文件
 $ docker-compose -f  redis.yaml up -d							
 
 # 查看所有运行的容器
 $ docker-compose ps									
 # 查看所有编排容器,包括已停止的容器
 $ docker-compose ps -a		
 
 # 停止所有容器,删除所有容器,移除自定义网络
 $ docker-compose down	
 # 停止指定的容器,如果不指定则停止所有的容器
 $ docker-compose stop container_name		
 # 启动指定的容器,如果不指定则启动所有的容器
 $ docker-compose start container_name		
 # 删除指定的已停止容器,如果不指定则删除所有已停止容器
 $ docker-compose rm container_name		
	
 # 暂停web容器
 $ docker-compose pause web
 # 恢复web容器
 $ docker-compose unpause web

 # 查看各个服务容器内运行的进程 
 $ docker-compose top

多容器部署

创建docker-compose.yml文件

把以下内容放到docker-compose.yml 文件中,根据自己的项目进行配置。

version: "3.3"
services:
  redis: 
    container_name: redis #容器名称
    image: redis:latest #镜像名称
    restart: always  #重启docker引擎后该容器也重启
    ports: 
        - "6379:6379" #本地端口号与容器内部端口号
    volumes: #指定挂载目录
        - /data/redis/redis.conf:/etc/redis/redis.conf
        - /data/redis/data:/data
    command: redis-server /etc/redis/redis.conf  #使用command可以覆盖容器启动后默认执行的命令。这里启动执行指定的redis.conf文件
  mysql: 
    container_name: mysql #容器名称
    image: mysql:5.7.34 #镜像名称
    restart: always  #重启docker引擎后该容器也重启
    ports: 
        - "3306:3306" #本地端口号与容器内部端口号
    volumes: #指定挂载目录
        - /data/mysql/data:/var/lib/mysql
        - /data/mysql/conf/my.cnf:/etc/mysql/my.cnf
        - /data/mysql/log:/var/log/mysql
    environment:
        MYSQL_ROOT_PASSWORD: root       #数据库初始话为root用户设置的默认密码
        #MYSQL_DATABASE: mproject       #数据库名
        #MYSQL_USER: mao                #自定义数据库的用户,权限只作用于MYSQL_DATABASE配置的数据库
        # MYSQL_PASSWORD: mao123        #自定义数据库的用户,权限只作用于MYSQL_DATABASE配置的数据库
  nginx: 
    container_name: nginx #容器名称
    image: nginx:latest #镜像名称
    restart: always  #重启docker引擎后该容器也重启
    ports: 
        - "80:80" #本地端口号与容器内部端口号
    volumes: #指定挂载目录
        - /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
        - /data/nginx/html:/usr/share/nginx/html
  java: 
    container_name: java
    # 根据当前目录下的Dockerfile文件创建镜像
    build: .
    restart: always  #重启docker引擎后该容器也重启
    ports: 
        - "5050:5050"
    depends_on: 
        - redis #依赖redis
        - mysql #依赖mysql
    environment:
        TZ: Asia/Shanghai

java启动时需要redismysql容器都启动好了之后才能成功启动,否则会报错,所以需要设置依赖depends_on

准备挂载目录

在服务器中,创建一个data文件夹来保存docker的数据卷内容,容易管理。mysql、nginx、redis 启动的时候都需要根据各自的配置文件启动,所以要把配置文件提前准备好放到挂载目录的对应位置上。以nginx为例,上面 yml 中的 nginx.conf 挂载到 /data/nginx/conf/目录下。此时宿主机下的 data 目录大概为这样,用来存储数据和配置文件。

图片.png

配置文件

这里给大家参考下笔者的配置,也可以直接下载使用~

图片.png

链接:pan.baidu.com/s/1bz45CXQH… 提取码:8wfn

Dockerfile构建java镜像

除了java,其他镜像都可以直接pull拉取就行,java的话需要自己创建镜像,此时就要用到 Dockerfile 来构建 java镜像了

上面的yml文件中,java镜像是根据这个Dockerfile文件进行创建的,所以要事先准备好这个文件,放在docker-compose.yml同级的目录中,文件名称不能变,build:.是寻找当前目录下名为Dockerfile的文件创建镜像。

# 基础镜像
FROM centos:7.9.2009
# 配置环境变量和jdk的安装目录
ENV JAVA_DIR=/usr/local
# 安装jdk
# \ 就是换到下一行输入,对实际命令没有任何影响,只是为了方便观看
COPY ./jdk-8u351-linux-x64.tar.gz $JAVA_DIR/
COPY ./fabledt-admin.jar /tmp/app.jar

RUN cd $JAVA_DIR \ 
    # 使用tar命令将当前目录下(这里因为上面配置了所以所在的目录也就是 /usr/local/下面)的jdk文件进行解压
    && tar -xvf ./jdk-8u351-linux-x64.tar.gz \
    # 然后修改解压后的文件名为java8 ,此时就是 /usr/local/java8
    # 这里需要注意的是下面的 jdk1.8.0_321,他就是解压后的文件名
    # 如果这里你不清楚解压后的文件是什么,则可以先解压看以下文件名是什么,然后在进行书写这里的名称
    && mv ./jdk1.8.0_351 ./java8 
    
# 配置JAVA的环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
# 配置到PAHT中
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口 5050 -- 容器内部java配置的端口暴露出来
EXPOSE 5050

# 入口,jar文件的启动命令 # 这里app.jar就是我的jar文件
#ENTRYPOINT ['java','-jar','/tmp/app.jar'].
CMD java -jar /tmp/app.jar 

nginx注意点

  • conf 目录 ———— 上传nginx.conf配置文件
  • html 目录 ———— 上传前端包

nginx中需要把配置文件nginx.conf和html文件挂载到宿主机中,方便修改配置和上传静态文件;docker中的nginx.conf需要修改一下server下的root,不然浏览器访问的时候会找不到静态文件;这里我们要进到dockernginx容器中去看下html的路径在哪。

图片.png

可以看到在/usr/share/nginx/html目录下,此时需要改下nginx.conf配置,这样就可以正常访问页面了。

图片.png

Tips: 每次修改nginx.conf之后,只需要执行docker restart nginx即可重启成功

redis配置

因为需要redis的配置文件,这里最好还是去redis的官方去下载一个redis使用里面的配置文件即可

redis中文官方网站:www.redis.cn/download.ht…

下载解压出来 redis.conf 后,修改配置放到挂载的目录位置,即 /data/redis目录下。

图片.png

主要配置的如下:

bind 127.0.0.1 # 注释掉这部分,使redis可以外部访问

daemonize no # 用守护线程的方式启动

requirepass 你的密码 # 给redis设置密码

appendonly yes # redis持久化 默认是no

tcp-keepalive 300 # 防止出现远程主机强迫关闭了一个现有的连接的错误 默认是300

执行docker-compose

准备完成之后服务器中的目录是这样的👇

图片.png

进到当前目录中 cd /docker,直接执行 docker-compose up -d,来根据当前目录下的docker-compose.yml来创建各个容器,如果不是在当前目录下执行命令,则会报错,找不到docker-compose.yml文件。

不需要提前下载好对应的镜像,在执行docker-compose up -d的时候会自动根据文件中的image来拉取镜像,没有指定版本则拉取最新的镜像,方便很多。

图片.png

-d为后台执行,看不到具体的执行步骤,只会告诉你是否成功了,如上图所示则为全部创建成功。

本地没有对应的镜像,在执行docker-compose up 构建时,会自动拉去对应的images! 本地有镜像的话,就直接从本地的镜像构建容器!

Java重新部署

当更新迭代版本之后,需要再次部署的时候,只需要把java有关的镜像和容器删除掉,在重新执行docker-compose up -d就行,此时执行的时候,已有的容器会显示is up-to-date(是最新的,已存在了),只会去创建那些不存在的容器。

手动部署

1、查看一下运行中的容器

图片.png

2、需要把java的容器和镜像都删除掉,重新上传新的jar包,打包新的镜像生成新的容器。

图片.png

3、把重新打包的jar包放到/docker目录下,重新执行docker-compose up -d命令,来创建根据新的jar包生成镜像的容器,下图可以看到,只重新创建了java的容器,其他容器则没有动,这样java就完成了重新部署。

图片.png

脚本自动部署

在项目的根目录下,创建一个deploy.sh文件用来写部署脚本

#!/usr/bin/env bash

# 打包
mvn package

# 到jar包目录
cd ry-admin/target/

# 把jar包上传到服务器
scp ry-admin.jar root@192.168.11.11:/docker

# 登录目标服务器后运行双引号后面的脚本
ssh root@192.168.11.11 "
  cd /docker
  echo "进入docker目录"
  docker rm -f java
  docker rmi docker_java
  docker-compose up -d
  echo "构建java容器成功"
  "

这里使用scp和ssh命令会让你手动输入目标服务器密码,每次输入密码会很烦,怎么办呢?服务器和本机关联一下密钥就可以不用每次输入密码了,可以看下我的这篇文章# windows怎么关联ssh服务器,实行免密登录

直接使用Ideal中的Termeinal终端,执行当前这个文件 sh deploy.sh 即可。

默认的cmd终端是不能执行sh脚本文件的,点击Settings改为默认Bash;但是需要提前下载Git工具可以参考我的这篇文章下载Git ,才会有Bash选项。

图片.png

图片.png

如上图,在Ideal中就可以直接把jar包部署到服务器并且启动服务。

查看日志

直接使用docker logs查看日志,java为容器的NAMES,这种方式看不了动态的日志。

图片.png

动态查看日志

使用 docker inspect 找到java容器的 LogPath ,再动态查看这个日志即可!

# 找到日志路径
$ docker inspect java | grep LogPath

# 动态查看日志
$ tail -f xxxx.log

图片.png

查看容器

使用docker-compose部署的容器,可以通过 docker-compose ps 查看已经启动的容器,

图片.png

也可以通过 docker ps 来查看所有的已启动的容器

图片.png

如果想要重启docker-compose部署的某个容器,不需要重新执行 docker-compose up 命令,直接使用 docker restart xxx 即可。

图片.png

案例

下面这个系统就是用上面的 docker-compose.yml 部署的,以供参考~

案例系统 >>>> 点击跳转