學習Spring Boot:(二十三)Spring Boot 中使用 Docker

前言

簡單的學習下怎麼在 Spring Boot 中使用 Docker 進行構建,發佈一個鏡像,如今咱們經過遠程的 docker api 構建鏡像,運行容器,發佈鏡像等操做。css

這裏只介紹兩種方式:java

  1. 遠程命令 api (須要知道 Docker 命令)
  2. maven 插件 (不須要了解 Docker 命令)

開啓 Docker api 遠程訪問

開啓 docker api 遠程操做的功能,
例如,centos 7 中在 /usr/lib/systemd/system/docker.service,文件中,修改 ExecStart 的參數:mysql

ExecStart=/usr/bin/dockerd  -H tcp://0.0.0.0:2375  -H unix:///var/run/docker.sock

端口自定義設置便可。git

重載全部修改過的配置文件,而且重啓 docker,github

systemctl daemon-reload    
systemctl restart docker.service

須要注意的是,因爲沒有密碼登錄任何權限驗證,外網或者生產環境須要上證書使用。web

命令方式構建鏡像

這種方式其實很是簡單,就是須要懂得 docker 命令,才能操做。spring

通過上面開啓 Docker Api 後,咱們可使用網絡環境操做 Docker 引擎了。sql

  1. 新建 Dockerfile 構建鏡像文件,新建立一個文件夾,專門放構建鏡像須要的文件,我建立的是 /src/docker/docker

    FROM java:8
    EXPOSE 8080
    
    VOLUME /tmp
    ADD springboot-docker.jar app.jar
    ENTRYPOINT ["java","-jar","/app.jar"]
  2. 執行 maven 命令 ,將項目打包 mvn clean package --DskipTests,而後將打好的 jar 包,也放入到 Dockerfile項目目錄中。shell

  3. 而後進入 src/docker 目錄下執行 :

    docker -H tcp://xxx.xxx.xxx.xxx:2375 build -t test .

    開始構建鏡像:

    Sending build context to Docker daemon  31.74MB
    Step 1/5 : FROM java:8
    ---> d23bdf5b1b1b
    Step 2/5 : EXPOSE 8080
    ---> Using cache
    ---> 060a43a42146
    Step 3/5 : VOLUME /tmp
    ---> Using cache
    ---> b4f88fde6181
    Step 4/5 : ADD springboot-docker.jar app.jar
    ---> 3a40188825b0
    Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
    ---> Running in ab093916fc4c
    Removing intermediate container ab093916fc4c
    ---> 45a3966feb60
    Successfully built 45a3966feb60
    Successfully tagged test:latest

使用 docker-maven-plugin構建鏡像

在 maven 項目下加入 docker-maven-plugin

<!--打包docker插件相關參數的配置-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.14</version>
                <configuration>
                    <!--打包的鏡像名-->
                    <imageName>${project.groupId}/${project.artifactId}</imageName>
                    <!--Dockerfile文件位置,以項目的 root 目錄爲根節點,建議到單獨創建一個目錄-->
                    <dockerDirectory>./src/docker/</dockerDirectory>
                    <!--Docker 遠程的 API 地址及端口-->
                    <dockerHost>http://xxx.xxx.xxx.199:2375</dockerHost>
                    <imageTags>
                        <imageTag>latest</imageTag>
                    </imageTags>
                    <!--執行構建docker鏡像的時候須要哪些文件,springboot項目指定 打包好的jar 鏡像就好-->
                    <resources>
                        <resource>
                            <!--這裏指定的文件是target中的jar文件-->
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

建立 Dockerfile

須要跟pom.xml 上面配置的路徑保持一致,因此個人路徑是 ${baseProjectFolder}/src/docker的文件夾下新建一個文件 Dockerfile,添加構建 docker 相關命令參數:

FROM java:8
EXPOSE 8080

VOLUME /tmp 
ADD springboot-docker.jar app.jar # 根據打包的jar 包文件名進行修改
ENTRYPOINT ["java","-jar","/app.jar"]

打包

在應用的根目錄下執行命令(打包加 dokcer build):

$ mvn clean package docker:build -DskipTests

好比使用個人工程,進行打包後完成了 docker 的構建的信息:

[INFO] Building image com.wuwii/springboot-docker
Step 1/5 : FROM java:8

 ---> d23bdf5b1b1b
Step 2/5 : EXPOSE 8080

 ---> Running in b7936baae57f
Removing intermediate container b7936baae57f
 ---> 060a43a42146
Step 3/5 : VOLUME /tmp

 ---> Running in 65e2b8ac44d3
Removing intermediate container 65e2b8ac44d3
 ---> b4f88fde6181
Step 4/5 : ADD springboot-docker.jar app.jar

 ---> aa3762cda143
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]

 ---> Running in d9f5f63b9736
Removing intermediate container d9f5f63b9736
 ---> 622a7d1e315c
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 622a7d1e315c
Successfully tagged com.wuwii/springboot-docker:latest

使用鏡像

  1. 進入安裝 docker 的主機中,使用命令查看鏡像(IMAGE ID 和上面是一致的):

    $ docker image ls com.wuwii/springboot-docker
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    com.wuwii/springboot-docker   latest              622a7d1e315c        22 minutes ago      659MB
  2. 運行容器:

    $ docker run -d -p 8080:8080 --name learn  com.wuwii/springboot-docker
    
    180fe4a7ddfc10c0cf2c37649ae1628e804564bfe1594ef05840e707801e6da3

    監聽 8080 端口,測試是否成功。

服務編排 compose

通常的咱們的 WEB 項目會使用到不少外部工具,例如 Redis ,MYSQL, ES等,若是一個一個啓動搭建部署,太麻煩了,還要測試若是把這個一套環境拿到別的地方還能用嗎?

使用服務編排能夠避免這些坑。

加入咱們的項目中增長了 Mysql 的數據庫,在根目錄新建一個 docker-compose.yml

version: '3'
services:
  web:
    depends_on:
      - db
    ports:
      - "8080:8080" # 建議加上引號,若是單獨兩位數的數字,可能出現解析問題
    restart: always
   # build:
    # context: ./src/docker # Dockerfile 文件的目錄,能夠遠程地址,絕對 or 相對
     # dockerfile: Dockerfile # 若是你的 Dockerfile 重命名了,須要指定
    image: test:latest
    environment:
      DB_HOST: db:3306
      DATABASE: learn
      DB_USERNAME: root # 測試用下 root
      DB_PASSWORD: 123456 # # 建議使用 secret

  db:
    image: mysql:5.7
    volumes:
        - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: learn
      MYSQL_USER: kronchan
      MYSQL_PASSWORD: 123456

volumes:
  db_data:  # 使用的數據卷必須聲明

上面我使用的是前面已經構建好的鏡像,而後執行的編排,更好的是直接使用 build 讓它本身編排服務。

系統配置文件application.yml使用缺省值的方式,不影響開發的使用:

spring:
  datasource:
    url: jdbc:mysql://${DB_HOST:localhost:3306}/${DATABASE:learn}?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD:123456}
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL57Dialect # 方言根據 數據庫版本選擇吧

也可使用不一樣的 spring.profiles指定不一樣的環境,在 docker-compose.yml 中覆蓋執行命令指定環境也是常見作法的:command: mvn clean spring-boot:run -Dspring-boot.run.profiles=xxx

最後啓動,在 docker-compose.yml目錄下執行 : docker-compose up

關閉服務 docker-compose down

注意

docker-compose 順序的問題,這個是開始學習編排的時候須要注意的問題,若是上面的服務編排中 mysql 啓動的慢, web 項目就會啓動失敗,它啓動的時候不知道被依賴的服務是否啓動完成,就會出現這樣的問題。

解決的辦法有如下幾種:

  • 足夠的容錯和重試機制,好比鏈接數據庫,在初次鏈接不上的時候,服務消費者能夠不斷重試,直到鏈接上位置
  • docker-compose拆分,分紅兩部分部署,將要先啓動的服務放在一個docker-compose中,後啓動的服務放在兩一個docker-compose中,啓動兩次,二者使用同一個網絡。
  • 同步等待,使用wait-for-it.sh或者其餘shell腳本將當前服務啓動阻塞,直到被依賴的服務加載完畢
    wait-for-it的github地址爲:wait-for-it

總結

  1. 主要是寫 Dockerfile 的時候最好單獨的拿出一個文件夾來放它,我開始的時候就是直接放在項目的根路徑,結果構建鏡像的時候老是出現了將其餘的文件也一塊兒複製到了 Docker 目錄中,WINDOW下使用 maven 插件操做這個須要注意這個上下文環境,否則很容易將一個磁盤的文件都拷貝進來了,初學者血的教訓。解決辦法就是單首創建一個文件夾,將須要的東西單獨放置,就不用考慮這麼多問題。

代碼

相關文章
相關標籤/搜索