I have a Spring Boot that that connects to a MySQL DB. I’m trying to Dockerize it and create a docker-compose.yml
that stands up a MySQL container and then stands up a Dockerized version of my Spring Boot app that can talk to it.
My project looks like this:
myapp/
src/
main/
java/
<All the Java code here>
resources/
application.yml
build/
libs/
myapp.jar
Dockerfile
.env
docker-compose.yml
When I run ./gradlew clean bootJar
it builds a build/libs/myapp.jar
.
My .env
file:
MAIN_DB_HOST=127.0.0.1
MAIN_DB_PORT=3307
MAIN_DB_DOCKER_PORT=3306
MAIN_DB_USERNAME=root
MAIN_DB_PASSWORD=123456
MAIN_DB_ROOT_PASSWORD=123456
MAIN_DB_DATABASE=myapp_db
SERVER_PORT=9200
WS_PORT=9200
WS_DOCKER_PORT=9201
My Dockerfile
:
FROM eclipse-temurin:11
RUN mkdir /opt/app
COPY app/build/libs/myapp.jar myapp
ENTRYPOINT ["java","-jar","myapp"]
My docker-compose.yml
:
version: "3.8"
services:
myapp_db:
image: mysql:8.0.32
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=$MAIN_DB_ROOT_PASSWORD
- MYSQL_DATABASE=$MAIN_DB_DATABASE
- MYSQL_CHARSET=utf8mb4
- MYSQL_COLLATION=utf8mb4_0900_ai_ci
- MYSQL_ENGINE=InnoDB
ports:
- $MAIN_DB_PORT:$MAIN_DB_DOCKER_PORT
volumes:
- db:/var/lib/mysql
myapp:
depends_on:
- myapp_db
build: .
restart: on-failure
ports:
- $WS_PORT:$WS_DOCKER_PORT
- $MAIN_DB_PORT:$MAIN_DB_DOCKER_PORT
volumes:
db:
When I run ./gradlew clean bootJar && docker-compose --env-file .env up -d
I see my Docker image get built but when it starts up I get:
WARNING: Image for service myapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating myapp_myapp_db_1 ... done
Creating myapp_myapp_db_1 ...
Creating myapp_myapp_db_1 ... error
ERROR: for myapp_myapp_db_1 Cannot start service myapp: driver failed programming external connectivity on endpoint myapp_myapp_db_1 (33899c0810d03db26ef7b48e67328ea9eb4e0f75cebc0201e667db72ce21d7ba): Bind for 0.0.0.0:3307 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
Can anyone spot where I’m going awry?
>Solution :
You are trying to publish the same ports twice
services:
myapp_db:
ports:
- $MAIN_DB_PORT:$MAIN_DB_DOCKER_PORT
myapp:
ports:
- $MAIN_DB_PORT:$MAIN_DB_DOCKER_PORT
Having the same port number on the left-hand side of two ports:
lines will cause the "port is already allocated" error you see. However, the ports:
declaration routes network connections to a specific container; since myapp
isn’t running a database, it doesn’t need that ports:
line at all.
(The second ports:
number is a fixed value for whatever image you’re running; for MySQL, it will always be 3306. I wouldn’t bother including this in a .env
file. Also consider that ports:
are not used or required for connections between containers and you may not need ports:
for your database at all.)
You should delete the MAIN_DB_PORT
line for your application, but make sure to leave the line that publishes your application’s port.
services:
myapp_db:
ports:
- $MAIN_DB_PORT:3306 # optional
myapp:
ports:
- $WS_PORT:9201 # probably required
# - $MAIN_DB_PORT:3306 # <-- delete this one, causes the error