[TOC]
前言
之前我們用docker
部署了springboot
,redis
,mysql
的專案,但是是部署在三個不同的容器裡,還需要先知道redis
和mysql
的ip
地址,手動配置到springboot
應用容器裡,我只是想快速在本地進行測試啊,這樣成本太高了,有沒有什麼辦法,把他們集中管理呢?比如把它構建成為一個映象。
辦法總是有的,那就是Docker Compose
。
之前的專案地址:https://github.com/Damaer/Dem...
Docker Compose
1. Docker Compose是什麼?
Docker Compose
其實就是用來定義和執行復雜應用的Docker
工具,什麼叫複雜應用,比如前面寫的springboot
+redis
+mysql
,裡面就有三個容器,這種多個容器的,用一個工具來管理,它不香麼?
docker compose 通過配置檔案來管理多個Docker
容器,在配置檔案中,所有的容器通過service
來進行定義,然後使用docker-compose
指令碼來啟動、停止、重啟應用以及應用中的服務和所依賴的容器等。
2. Docker Compose 的具體步驟
一般是三個步驟:
- 使用
Dockerfile
來定義應用程式的環境 - 在
docker-compose.yml
定義構成應用程式的服務,這樣它們可以在隔離環境中一起執行。 - 執行
docker-compose up
命令來啟動並執行整個應用程式。
我使用的是Mac OS
,裝Docker
的時候已經把Docker Compose
也安裝好了,不需要單獨安裝。
3. 如何在IDEA專案裡面使用Docker Compose
首先pom.xml
檔案中需要注意配置小寫的artifactId
:
<groupId>com.aphysia</groupId>
<artifactId>dockerdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dockerdemo</name>
<packaging>jar</packaging>
除此之外還需要配置外掛:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<!-- 將外掛繫結在某個phase執行 -->
<executions>
<execution>
<id>build-image</id>
<!-- 使用者只需執行mvn package ,就會自動執行mvn docker:build -->
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
除此之外,Dockerfile
是必要的,上面的外掛中已經配置了我們dockerFile
需要放在<dockerDirectory>src/main/docker</dockerDirectory>
這個位置,DockerFile
裡面配置如下:
FROM openjdk:8-jdk-alpine
EXPOSE 8081
VOLUME /tmp
# 重寫命名為app.jar
ADD dockerdemo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
理論上到這個時候,我們使用mvn clean package
就會生成對應的jar
包:
docker compose
最重要的是配置docker-compose.yml
,這個檔案我們放在專案的根目錄就可以,和pom.xml
平級:
version: "3"
services:
redis:
image: redis:latest
restart: always
ports:
- "6389:6379"
volumes:
- /tmp/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_USER: 'root'
MYSQL_PASS: '123456'
ports:
- "3306:3306"
volumes:
- "./db:/var/lib/mysql"
- "./conf/my.cnf:/etc/my.cnf"
- "./init:/docker-entrypoint-initdb.d/"
# 指定服務名稱
webapp:
# 指定服務使用的映象
image: aphysia/dockerdemo
# 指定容器名稱
container_name: dockerdemo
# 指定服務執行的埠
ports:
- 8081:8081
# 指定容器中需要掛載的檔案
volumes:
- /etc/localtime:/etc/localtime
- /tmp/dockerdemo/logs:/var/logs
值得注意的點:
- service裡面就是我們配置的映象,包含了
redis
,mysql
,webapp
,webapp
其實就是我們的應用。 "6389:6379"
中6389
其實是我們主機的埠,也就是我的Mac
連線redis
容器需要使用6389
,而容器之間連線需要使用6379
,這是容器的埠。/tmp/redis.conf:/etc/redis/redis.conf
中/tmp/redis.conf
是主機的目錄,而這個目錄需要在docker裡面配置才可以,要不就會報錯(執行記得加管理員許可權):docker ERROR: * start service *: Mounts denied
mysql
8.0 可能會報錯java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
,這個是因為url
連結少了一個引數:allowPublicKeyRetrieval=true
啟動可能出現的坑點
啟動後可能連結不上mysql
或者redis
,但是看容器執行情況又是正常的:
DockerCompose % docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
32fd6ce598ba aphysia/dockerdemo "java -jar /app.jar" 7 minutes ago Up 7 minutes 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp dockerdemo
585b9b6bd71d redis:latest "docker-entrypoint.s…" 10 minutes ago Up 7 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp dockercompose_redis_1
d96ba57941d9 mysql:latest "docker-entrypoint.s…" 16 minutes ago Up 7 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp dockercompose_mysql_1
執行docker-compose up
沒有報錯,請求的時候報錯:
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1:6379
這是因為容器之間的請求不能用127.0.0.1
,必須用mysql
,redis
代表容器的網路,比如:jdbc:mysql://mysql:3306/test?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
完整的application.yml
:
server:
port: 8081
spring:
#資料庫連線配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql:3306/test?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
redis:
host: redis ## redis所在的伺服器IP
port: 6379
##密碼,我這裡沒有設定,所以不填
password:
## 設定最大連線數,0為無限
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
#mybatis的相關配置
mybatis:
#mapper配置檔案
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.aphysia.springdocker.model
#開啟駝峰命名
configuration:
map-underscore-to-camel-case: true
logging:
level:
root: debug
還有一個問題,就是docker-compose.yml
裡面配置的映象名字一定要對,要不docker-compose up
執行的時候,就會出現:
Pulling xxxx...
ERROR: The image for the service you're trying to recreate has been removed. If you continue, volume data could be lost. Consider backing up your data before continuing.
Continue with the new image? [yN]y
Pulling xxxx...
ERROR: pull access denied for postgresql, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
我還以為是登入的原因,本來是本地映象,應該直接create
而不是pull
,如果不知道名字,可以通過以下命令檢視,REPOSITORY
就是名字:
DockerCompose % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
aphysia/dockerdemo latest 1429aa26790a 54 minutes ago 137MB
<none> <none> ceb493583d7c 57 minutes ago 137MB
<none> <none> dffcc47602a2 About an hour ago 137MB
<none> <none> a695cf2cd2df About an hour ago 137MB
<none> <none> 209ce4f96d34 2 hours ago 137MB
redis latest 40c68ed3a4d2 10 days ago 113MB
mysql latest e1d7dc9731da 14 months ago 544MB
openjdk 8-jdk-alpine a3562aa0b991 2 years ago 105MB
最後啟動命令:
sudo docker-compose up
成功啟動:
啟動之後記得初始化一下資料庫資料表!!!
drop database IF EXISTS test;
CREATE DATABASE test;
use test;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT "",
`age` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (1, '李四', 11);
INSERT INTO `user` VALUES (2, '王五', 11);
至此,大功告成,看似簡單的命令,其實還是有不少坑點。
【作者簡介】:
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。個人寫作方向:Java原始碼解析
,JDBC
,Mybatis
,Spring
,redis
,分散式
,劍指Offer
,LeetCode
等,認真寫好每一篇文章,不喜歡標題黨,不喜歡花裡胡哨,大多寫系列文章,不能保證我寫的都完全正確,但是我保證所寫的均經過實踐或者查詢資料。遺漏或者錯誤之處,還望指正。