- 💻 Sword finger offer & leetcode question brushing warehouse: https://github.com/Damaer/CodeSolution
- Document address: https://damaer.github.io/CodeSolution/
- Warehouse introduction: Question brushing warehouse: CodeSolution
- 📒 Programming knowledge base: https://github.com/Damaer/Coding
- Document address: https://damaer.github.io/Coding/#/
- preface
- Docker transformation
- 1. Plug in configuration
- 2. DockerFile file configuration
- 3. Run in jar package mode
- 4. Maven & docker compilation
- 5. Error reporting solution
- Pit point
preface
The local projects based on springboot,redis and mybatis have been built. Redis and mybatis are all run in docker, but the whole project still runs on IDEA. It's better to toss around and let the project run on docker.
Note: the project is transformed from the previous project: How to quickly build a Springboot + Mysql + Redis project based on Docker
Project address: https://github.com/Damaer/DemoCode/tree/main/springboot/springDocker
Docker transformation
1. Plug in configuration
First, you need to add docker's maven packaging plug-in in the pom file:
<plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>1.0.0</version> <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>
Several items are configured:
- ${docker.image.prefix}: prefix of image name. Here I use aphysia
- ${project.artifactId}: artifactId of the project, coordinates
- < dockerdirectory > Src / main / docker < / dockerdirectory >: configure the file path that docker needs to generate the image
2. DockerFile file configuration
Therefore, we need to create a docker folder under src/main with DockerFile in it to generate a docker image:
FROM openjdk:8-jdk-alpine EXPOSE 8081 VOLUME /tmp ADD springbootdocker-0.0.1-SNAPSHOT.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]
- FROM: which image to build is based on, based on openjdk:8-jdk-alpine
- Export: which ports does the docker container need to listen to when running? We use 8081
- VOLUME: data VOLUME, which is used to store persistent data. Generally, the data should be persistent to the host, otherwise the container will be deleted, and the data will be lost. Therefore, VOLUME can correspond the directory on the host with the directory in the container as the persistent directory, It is equivalent to creating a temporary file in the / var/lib/docker directory of the host and linking it to the / tmp directory in the container.
- ADD: copy the jar package (file) to docker and rename it app jar
- ENTRYPOINT: Specifies the execution command to run the image. Here, use the java -jar command to run the jar package
For VOLUME, we can use the docker inspect eaf13c07d079daba6ecb8f2d59019ad053d79bbce1e6c8e10a52e79637730e70 command to check (the long string is the id of the image):

image-20211123083941908
We can see that there is such a paragraph:
"Mounts": [ { "Type": "volume", "Name": "e8863daa5874f6446560673f0a260a4fd2b127b71d31318e6546843f8b283a48", "Source": "/var/lib/docker/volumes/e8863daa5874f6446560673f0a260a4fd2b127b71d31318e6546843f8b283a48/_data", "Destination": "/tmp", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ]
Source is the directory in our host and Destination is the directory in our container. The two are associated, that is, the data volume.
3. Run in jar package mode
Since we need to copy the jar package earlier, where does the jar package come from? The answer is that we need to configure it to run as a jar package to see:
<groupId>com.aphysia</groupId> <artifactId>springbootdocker</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springbootdocker</name> <packaging>jar</packaging> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <docker.image.prefix>aphysia</docker.image.prefix> </properties>
After compiling and running, you will see that the jar package file is generated under target:

image-20211123084611668
4. Maven & docker compilation
First compile with maven in IDEA:
mvn clean package -U mvn clean install
At this time, I encountered some errors in environment variables, which are those of Maven and Java. Note that I need to configure them. I am a Mac and use zsh, so I need to configure the environment variables of zsh:
You can use open ~ / bash_ Profile and open ~ / Zshrc see the configuration inside:
export M2_HOME="/Users/aphysia/config/apache-maven-3.6.3" export PATH="$M2_HOME/bin:$PATH" export PATH JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home export JAVA_HOME CLASS_PATH="$JAVA_HOME/lib" PATH=".$PATH:$JAVA_HOME/bin"
After modification, remember to use source ~ / bash_ Refresh the profile.
After mvn is compiled, a jar package is generated. We can run it with the Java jar command:
java -jar springBootDocker-0.0.1-SNAPSHOT.jar
If there is no problem, you can compile the image with the docker command:
mvn docker:build -Dmaven.test.skip
DockerFile file, five steps are successful:

image-20211123090108680
View docker image:
% docker images REPOSITORY TAG IMAGE ID CREATED SIZE aphysia/springbootdocker latest dde6911c8e25 47 hours ago 137MB <none> <none> ee52277559a6 47 hours ago 137MB redis latest 40c68ed3a4d2 5 days ago 113MB redis <none> 84c5f6e03bf0 14 months ago 104MB mysql latest e1d7dc9731da 14 months ago 544MB docker/getting-started latest 1f32459ef038 16 months ago 26.8MB openjdk 8-jdk-alpine a3562aa0b991 2 years ago 105MB
It's time to compile and run the image using docker (please run Redis and Mysql image first):
docker run -p 8081:8081 -t aphysia/springbootdocker
5. Error reporting solution
The above command is executed, and there seems to be no error, but the request is: http://localhost:8081/getUserList The following errors are reported when:
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1:6379 Caused by: java.net.ConnectException: Connection refused at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:1.8.0_212] at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~[na:1.8.0_212] at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:707) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_212] 2021-11-23 15:50:08.446 DEBUG 1 --- [ioEventLoop-4-1] io.lettuce.core.RedisChannelHandler : closeAsync() 2021-11-23 15:50:08.447 DEBUG 1 --- [ioEventLoop-4-1] i.lettuce.core.protocol.DefaultEndpoint : [unknown, epid=0x1] closeAsync() 2021-11-23 15:50:08.464 DEBUG 1 --- [ioEventLoop-4-1] io.lettuce.core.protocol.CommandHandler : [channel=0x6d227ef0, [id: 0x5a58ec1f] (inactive), epid=0x1, chid=0x1] channelUnregistered() 2021-11-23 15:50:08.467 DEBUG 1 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379 2021-11-23 15:50:08.478 ERROR 1 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379] with root cause java.net.ConnectException: Connection refused at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:1.8.0_212] at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~[na:1.8.0_212] at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:707) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.69.Final.jar!/:4.1.69.Final] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]
What is the reason?
The reason is that the network between each container in docker is isolated from each other. We use 127.0.0.1 in the application. Of course, the local network is used when running in IDEA, but when deployed in docker container, localhost must use the container itself, but the application container itself does not have redis or mysql, so the request fails
Simply put: because the ip addresses between containers are isolated, they cannot be accessed through local ports.
How can we solve it?
We can check whether the container really has its own ip. We can first use docker images to view the image, then docker exec -it c178e8998e68 bash(c178e8998e68 is the container id), and then use cat -etc/hosts to view the ip:
% docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3f27e28aa3f6 aphysia/springbootdocker "java -jar /app.jar" 9 minutes ago Up 9 minutes 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp epic_mendeleev c178e8998e68 mysql "docker-entrypoint.s..." 21 hours ago Up 21 hours 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql 7a5056f4c28b redis "docker-entrypoint.s..." 21 hours ago Up 21 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis % docker exec -it c178e8998e68 bash root@c178e8998e68:/# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 c178e8998e68
Or you can directly click cli from docker, and use cat -etc/hosts to view the ip. You can see that the external ip of the container is 172.17.0.3:

image-20211124230444387
Similarly, we can get the ip of mysql container, reconfigure the link in the project, repackage it, run docker, and then visit http://localhost:8081/getUserList , you can see that the container log is normal.

image-20211124230907588
Pit point
When using the docker command to build the image, the following error messages appear:
Failed to execute goal com.spotify:docker-maven-plugin:1.0.0:build (default-cli) on project dockerDemo: Exception caught: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: org.apache.http.client.ClientProtocolException: Cannot retry request with a non-repeatable request entity: Connection reset by peer -> [Help 1]
I've encountered a Waterloo in my life. At first glance, it seems to be the docker made plugin problem of packaging plug-ins. After a search, I changed the version, but it doesn't work. My version:
<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> <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>
Finally, I found a problem. My previous project had capital letters, while < imagename >
There are corresponding discussions on GitHub: https://github.com/spotify/docker-maven-plugin/issues/357

image-20211124231536247