docker-compose部署springboot项目

mysql,oauth,java

Posted by elmagnifico on November 4, 2020

Foreword

使用docker来部署springboot项目网上已经有很多了,但是他们有些细节问题没给说怎么弄,不过springboot本身的教程里就有对docker的详细教学,就不再说了,我这里是用docker-compose来组织多个service的,所以记录一下相关的问题。

最后的引用中2篇文章都写的非常清楚了,这里主要是说一下他们没注意或者同项目重复部署的时候遇到的坑。

Dockfile

我的dockfile做的比较简单,基本只要基础的能编译就行了,剩下的执行什么的都交给docker-compose来做了

FROM maven:3.6-jdk-8

#MAINTAINER demo [email protected]
#VOLUME /tmp
#ADD demo-0.0.1-SNAPSHOT.jar demo.jar
#RUN bash -c 'touch /demo.jar'
#EXPOSE 4396
#ENTRYPOINT ["java", "-jar", "demo.jar"]

pom.xml

当然由于本身使用maven插件来编译的所以pox里也要导入对应依赖

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <imageName>demo:1.0.0</imageName>
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

docker-compose.yml

平常看教程也好,什么其他的也好,都是类似这么写的配置文件,如果只启动单个应用完全没问题,但是启动多个就会出错了。

同时mysql同步到本地,web的一部分内容也同步到本地保存

version: '3'
services:
  mysql:
    container_name: docker_mysql
    image: docker.io/mysql
    environment:
      MYSQL_DATABASE: elmagnifico__au
      MYSQL_ROOT_PASSWORD: 123
    volumes:
      - /root/mysql/data:/var/lib/mysql
      - /root/mysql/config/my.cnf:/etc/my.cnf
      - /root/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - elmagnifico_net
    ports:
      - "3306:3306"
    command: [
      '--default-time-zone=+8:00'
    ]
    restart: always

  web:
    container_name: web
    restart: always
    build:
      context: ./src/main/docker
      dockerfile: Dockerfile
    working_dir: /web
    volumes:
      - .:/web
      - ~/.m2:/root/.m2
      - /root/log/web:/web/log
    networks:
      - elmagnifico_net
    ports:
      - "80:80"
      - "443:443"
    environment:
      - TZ=Asia/Shanghai
    depends_on:
      - mysql
    command: mvn clean spring-boot:run -Dspring-boot.run.profiles=prod

networks:
  elmagnifico_net:

问题

上面的看起来没问题,当时是写了一个脚本来同时启动两个服务器,但是就会出现都起不来的情况

http://elmagnifico.tech/2019/09/04/Mysql-Port-Collison/

之前在这里说过,同时将两个服务写道一个配置文件里会出错,因为二者先后build,会导致前一个刚启动的情况下,后一个立马重build,然后文件就出错了,就会出现二者反复启动,直到一方启动后无错,然后另一方才能正常启动。后来是通过分开两个服务,然后中间等待一段时间再启动另一个服务就正确了。

其实我之前只解了一半的问题,还有一个问题没有彻底解决。

就是我启动两个项目都是在同一个项目文件夹中的,没有给test和prod区分项目,这就导致了docker中

    volumes:
      - .:/web

这个将本地和docker中的内容,一直保持同步,从而导致二者启动时各种问题。

而要解决这个问题,就是部署的时候,分别建立两个工程文件夹,分别从各自的文件夹中进行build,独立二者。

deploy.sh

写了个自动部署,比较简单,用来启动正式服务和测试服务

#!/usr/bin/env bash
echo "start deploy"
echo "close exist service"
docker-compose -f ../web_test/test.yaml down
docker-compose -f ../web/docker-compose.yaml down
echo "deploy the prod"
docker-compose -f ../web/docker-compose.yaml up -d
echo "deploy the test"
docker-compose -f ../web_test/test.yaml up -d
echo "deploy end"

undeploy.sh

关闭所有服务

#!/usr/bin/env bash
echo "start undeploy"
echo "close test image"
docker-compose -f ../web_test/test.yaml down
echo "undeploy the prod"
docker-compose -f ../web/docker-compose.yaml down
echo "undeploy end"

Summary

这样以后,再也不会有什么启动的时候各种异常情况了。

不过这种方法还是傻了点,springboot本身也带了docker,其实也可以用spring本身的docker,生成镜像以后再启动,这样的话其实可以把不同service都写在同一个配置文件中。

Quote

http://www.ityouknow.com/springboot/2018/03/28/dockercompose-springboot-mysql-nginx.html

https://spring.io/guides/topicals/spring-boot-docker