Deploy a Spring Boot + Vue application using Docker on CentOS 8, with containers for Spring Boot, MySQL, Redis, and Nginx. This includes building the Spring Boot image Dockerfile, bridging container interconnection, directory mapping, and more.
Basic Environment#
- Enable port forwarding for the CentOS firewall
firewall-cmd --add-masquerade --permanent
- Restart the firewall
firewall-cmd --reload
-
Create directories
Create a /data folder in the root directory to uniformly save files mounted to the container
- /data/redis/data: [directory] saves Redis persistent data
- /data/redis/redis.conf: [file] Redis configuration file
- /data/nginx/html: [directory] Nginx HTML file directory
- /data/nginx/log: [directory] logs
- /data/nginx/nginx/nginx.conf: [file] Nginx configuration file
Network#
- Create a Docker subnet
docker network create --subnet 192.168.0.0/16 --gateway 192.168.0.1 docker-net
192.168.0.0/16: subnet range
192.168.0.1: gateway address
docker-net: subnet name
- View after creation
docker network inspect docker-net
[
{
"Name": "docker-net",
"Id": "1fc4884e63c593800fbbf263d10c09a8dadb52307096d57a5b2e80f84574ab90",
"Created": "2023-01-11T19:18:32.691672677+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
-
Join the network
-
Add
--net docker-net
to the Docker startup parameters -
After the container starts, use the command
docker network connect docker-net <container ID/NAME>
-
Redis#
- Download the Redis Docker image
docker pull redis
- Create the Redis configuration file
vi redis.conf
- Write to the redis.conf file
requirepass <your redis password>
- Start Redis
docker run -d -p 6379:6379 --name docker-redis --restart always -v /data/redis:/etc/redis -v /data/redis/data:/data --net docker-net redis redis-server /etc/redis/redis.conf
-d: run in the background
-p: port mapping, host port 6379 mapped to container port 6379
--name: name of the container after startup
--restart always: container auto-restart
-v: file mount maps the directory inside the container to the host, the left side is the host address, the right side is the container address
--net docker-net: join the Docker subnet
- After starting, use
docker ps -a
to check if the container started normally
MySQL#
- Get the image
docker pull mysql:8.0.25
":" is used to specify the MySQL version
- Start the MySQL container
docker run -d -p 3306:3306 --name d-mysql --net docker-net --restart always -e MYSQL_ROOT_PASSWORD=mysqlpwd -e MYSQL_USER=violet -e MYSQL_PASSWORD=Dd112211 mysql:8.0.25
-e MYSQL_ROOT_PASSWORD=mysqlpwd: -e indicates custom parameters, root user password
-e MYSQL_USER=violet: create a user when the container starts
-e MYSQL_PASSWORD=Dd112211: the password for that user
Other parameters can be viewed at docker hub mysql
- Set user permissions
You can grant permissions to the user created when the container starts or allow the root user to log in remotely.
Enter the container
docker exec -it d-mysql /bin/bash
Enter MySQL client
mysql -uroot -p
Set root to allow remote login
grant all privileges on *.* to 'root'@'%';
Refresh permissions
FLUSH PRIVILEGES;
- Exit MySQL client and exit the Docker container
exit
- Import MySQL database data into Docker MySQL
Execute in MySQL client
mysqldump -uroot -p --databases arrogant javawebsql my_blog springcloud vote_sys >/data/mysql/data-backup.sql
Use mysqldump to download data and save it in an executable SQL file
/data/mysql/data-backup.sql: directory and final generated SQL file name
--databases and the directory in between are the names of the databases to be dumped
Copy the SQL file into the MySQL container
docker cp /data/mysql/data-backup.sql d-mysql:/home/
Enter the MySQL container, enter the MySQL client, execute the command to write the data, must enter from the SQL file directory
source data-backup.sql
Build Spring Boot Image#
- Set application.yml
Set the database address to d-mysql, which is the name of the MySQL Docker container
url: jdbc:mysql://d-mysql:3306/my_blog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
Set the Redis address to d-redis
host: d-redis
- Create a Dockerfile in the src directory
FROM openjdk:8
LABEL maintainer=lnbiuc
COPY ./*.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
- Upload files
Place the Dockerfile and JAR file in the same directory
- Build the image
docker build -t api:8.8 .
-t: indicates the tag here, referring to the image version, api is the image name
.: the dot is very important, indicating to build in the current directory
- After the build is complete, check the image
docker images
- Start the container
docker run -d -p 8888:8888 -v /data/api:/log --name api --net docker-net --restart always api:8.8.3
Here the log folder is mounted out for easy viewing, the JAR file is in the root directory, so the log folder is also at the same level in the root directory.
Nginx#
- Pull the image
docker pull nginx
- Get the Spring Boot access address
docker network inspect docker-net
Output
[
{
"Name": "docker-net",
"Id": "1fc4884e63c593800fbbf263d10c09a8dadb52307096d57a5b2e80f84574ab90",
"Created": "2023-01-11T19:18:32.691672677+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"00729e5b41d6ddcec195722869e57d1baf7bd754793cac7f986d452032b6810d": {
"Name": "d-redis",
"EndpointID": "2ea0446903341146ccc741aac0431ae3f3e0e6acc8972763f024136a3499a0ae",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"0682772aaec9f7d6bb435cf0d38e478c5298fa577783a226d086867d71bcf4b3": {
"Name": "d-nginx",
"EndpointID": "97dde4d3e0b8fff81722518b3b62094af5f0c1b1b484ef112c7db3490fb89ee7",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"27325e2b869eb28534e5a3e65de5eb8a650fa8488ded994de46cbb271af40a17": {
"Name": "d-gitea",
"EndpointID": "1a9ab8e968041b4df12ebaacecb74a166f23438cbba9b5345878c6fa672d982d",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"bf2d1cf717fbc3a39c06068bba9638ad6ce49d407b3a6e28c196803188597038": {
"Name": "api",
"EndpointID": "34a832756b3c9c051d67e096f27448a80165407579de0a25877fe4d4e9f6e5d3",
"MacAddress": "02:42:c0:a8:00:05",
"IPv4Address": "192.168.0.5/16",
"IPv6Address": ""
},
"ebb72c81a769e9e8385cdbf910a5845ae3f53d8cd8e4d3d317046dd726b74947": {
"Name": "d-mysql",
"EndpointID": "c86a7becc085a4f47a35a8488b81bef771e0ae9f6eadd7e41d0db2beae3a8862",
"MacAddress": "02:42:c0:a8:00:06",
"IPv4Address": "192.168.0.6/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
The IPv4Address under the name api is the address that Nginx needs to reverse proxy.
- Prepare the SSL certificate and nginx.conf file, place them in the /data/nginx/nginx directory
My nginx.conf
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
# include enable-cors.conf
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
gzip on;
gzip_static on;
gzip_min_length 1k;
gzip_comp_level 7;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
server {
listen *:80;
listen [::]:80;
server_name beyondhorizon.top;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen *:80;
listen [::]:80;
server_name www.beyondhorizon.top;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen *:443 ssl http2;
listen [::]:443 ssl http2;
server_name beyondhorizon.top www.beyondhorizon.top;
ssl on;
ssl_certificate beyondhorizon.top_bundle.crt;
ssl_certificate_key beyondhorizon.top.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
client_max_body_size 10m;
keepalive_timeout 70;
include /etc/nginx/default.d/*.conf;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location ~ /api/ {
add_header Cache-Control max-age=3600;
proxy_pass http://192.168.0.5:8888;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
- Upload HTML files to /data/nginx/html
- Start Nginx
docker run -d -p 80:80 -p 443:443 -v /data/nginx/html:/usr/share/nginx/html -v /data/nginx/nginx:/etc/nginx -v /data/nginx/log:/var/log/nginx --name d-nginx --restart always --net docker-net nginx
- If you modify the Nginx configuration file later, simply restart the container using the command
docker restart d-nginx
At this point, all containers should be started, and the website should be accessible normally.