Docker 容器化运行 MySQL Redis Nginx 以及 SpringBoot Jar 并配置反向代理

博文目录


说明

我在主机根目录建了一个 data 目录, 用于存储各容器的数据. 通过容器挂载数据卷的功能, 将容器的数据存储到主机的该目录下, 数据与容器做了分离, 实现了数据持久化

另外, 本文内容仅是我自己学习 Docker 之后摸索的一套方案, 我个人并不清楚企业中如何使用 Docker

环境

  • 这次是在 UCloud 云的 CentOS 8.3 上尝试安装 Docker, 但是因为 EOL 的原因, 出现了各种奇怪的问题, 网上的资料又是乱七八糟, 参差不齐的质量, 尝试多次全失败, 索性重装了和 CentOS 同源的 Rocky 9.1 操作系统, 这下舒服了, 所有问题全没了. 这里也推荐对 Linux 一知半解的小伙伴直接上 Rocky

镜像加速? No! save:scp:load Yes!

国内不能访问真正的互联网, 给我们无数 Coder 创造了无数的困难

网上的方法是配置镜像加速器, 我自己测试了一圈, 发现只有阿里云的镜像加速勉强能用, 但是阿里云的镜像库比较老, latest 版本基本不对, 很多新版本的镜像也拉不下来, 不能满足使用要求

所以我开发了 save:scp:load 大法, 具备 免费, 简单, 高速, 最新版本 等特点, 官方有的我都可以用

Play with Docker (PWD)

Docker 提供了一个免费的工具 Play with Docker, 我们可以使用该工具来做我们主机能做的所有事情, 该工具连接着真正的互联网, Docker 体验相当不错

浏览器打开 Play with Docker, 关联 Docker Hub 账户, 点击 Start, 再点击 ADD NEW INSTANCE, 开始使用真正的 Docker 环境

操作流程

Docker 提供了 saveload 命令, 用来备份和载入镜像, Linux 有一个 scp 命令, 用于在服务器间安全地拷贝文件, 中途需输入服务器密码等信息. 所以, 我们可以在 PWD 把镜像打包, 然后传到我们自己的服务器, 再载入该镜像, 即可成功安装对应镜像

redis:7.0.11 为例 (国内配了阿里云加速器也拉不下来)

# 在 Play with Docker 操作
docker pull redis:7.0.11
docker save -o redis.tar redis:7.0.11
# 将 redis.tar 传输到我的服务器的 /data/docker 目录下, 中途需要输入我们主机的密码
scp redis.tar root@ip:/data/docker
# 在我们主机操作
docker load -i redis.tar

以下是在我的主机通过 save:scp:load 下载好的镜像

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
mysql        8.0.33    91b53e2624b4   5 days ago   565MB
redis        7.0.11    8e69fcb59ff4   6 days ago   130MB
nginx        1.25.1    eb4a57159180   6 days ago   187MB

MySQL

Docker Hub 查看 mysql 镜像的版本, 这里用 8.0.33

需要如下目录和文件

/data/mysql/data # 存放各种数据
/data/mysql/my.cnf # 配置文件

其中 my.cnf 的内容如下

[mysql]
#设置mysql客户端默认字符集
default-character-set=UTF8MB4

[mysqld]
#设置3306端口
port=3306
#服务端使用的字符集
character-set-server=UTF8MB4
#创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

创建并启动容器

docker run \
-d \
-p 3306:3306 \
--name mysql \
-v /data/mysql/data:/var/lib/mysql \
-v /data/mysql/my.cnf:/etc/mysql/conf.d/my.cnf \
-e MYSQL_ROOT_PASSWORD=Mrv587.. \
mysql:8.0.33

连接测试

docker exec -it mysql /bin/bash
docker exec -it mysql mysql -u root -p

Redis

Docker Hub 查看 redis 镜像的版本, 这里用 7.0.11

需要如下目录和文件

/data/redis/data # 存放各种数据
/data/redis/redis.conf # 配置文件

可以从 GitHub Redis 找到对应版本的 Tag, 找到 redis.conf 文件, 拷贝下来即可

修改 redis.conf 中的部分内容如下

# bind 127.0.0.1 # 解除只允许环回地址访问的限制
daemonize no # 修改为yes会使docker使用配置文件方式启动redis失败
save 900 1 # 如果上个900秒内有超过1次写操作,则保存快照
save 300 10
save 60 10000
logfile "redis.log" # 日志文件
requirepass Mrv587.. # 密码

创建并启动容器

docker run \
-d \
-p 6379:6379 \
--name redis \
-v /data/redis/data:/data \
-v /data/redis/redis.conf:/etc/redis/redis.conf \
redis:7.0.11 \
redis-server /etc/redis/redis.conf

连接测试

docker exec -it redis /bin/bash
docker exec -it redis redis-cli
auth Mrv587..

Nginx

Docker Hub 查看 nginx 镜像的版本, 这里用 1.25.1

需要如下目录和文件

/data/nginx/html # 存放前端项目
/data/nginx/log # 存放日志数据
/data/nginx/nginx.conf # 配置文件

默认配置文件内容如下, 自行复制到 nginx.conf 中

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    
    
    worker_connections  1024;
}


http {
    
    
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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;

    keepalive_timeout  65;

    #gzip  on;

    server {
    
    
	    listen       80;
	    listen  [::]:80;
	    server_name  localhost;
	
	    #access_log  /var/log/nginx/host.access.log  main;
	
	    location / {
    
    
	        root   /usr/share/nginx/html;
	        index  index.html index.htm;
	    }
	
	    #error_page  404              /404.html;
	
	    # redirect server error pages to the static page /50x.html
	    #
	    error_page   500 502 503 504  /50x.html;
	    location = /50x.html {
    
    
	        root   /usr/share/nginx/html;
	    }
	
	    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
	    #
	    #location ~ \.php$ {
    
    
	    #    proxy_pass   http://127.0.0.1;
	    #}
	
	    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
	    #
	    #location ~ \.php$ {
    
    
	    #    root           html;
	    #    fastcgi_pass   127.0.0.1:9000;
	    #    fastcgi_index  index.php;
	    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
	    #    include        fastcgi_params;
	    #}
	
	    # deny access to .htaccess files, if Apache's document root
	    # concurs with nginx's one
	    #
	    #location ~ /\.ht {
    
    
	    #    deny  all;
	    #}
	}
}

创建并启动容器

docker run \
-d \
-p 80:80 \
--name nginx \
-v /data/nginx/html:/usr/share/nginx/html \
-v /data/nginx/log:/var/log/nginx \
-v /data/nginx/nginx.conf:/etc/nginx/nginx.conf \
nginx:1.25.1

连接测试

docker exec -it nginx /bin/bash

访问测试, 用浏览器访问 IP 即可

SpringBoot Jar

创建工程

通过 Idea Spring Initializr 创建一个 Web 应用, 集成上面配置的 Redis 和 MySQL, 写个 Controller 能做简单的查询即可. 确保本地能够正常运行, 然后通过 Maven 打包成为可执行 Jar, 将 Jar 上传到服务器, 确保在服务器上该 Jar 也可以正常运行

创建镜像

在服务器上创建一个目录, 如 /data/app, 将 Jar 拷贝到该目录

创建 Dockerfile 文件, 并填入如下内容, 该内容可根据 Dockerfile 标准自行修改

# syntax=docker/dockerfile:1

FROM bellsoft/liberica-openjdk-centos:17.0.7-7
COPY *.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar", "--server.port=8080", "--logging.file.name=/app.out"]

其中, BellSoft Liberica JDKSpring 推荐使用的 JDK, 可通过 save:scp:load 大法先拉取该镜像. 未使用 WORKDIR 指定工作目录, 所以默认工作路径是根目录 /, 最后通过 ENTRYPOINT 指定运行 Jar 的方式, 并通过 Spring 参数指定日志位置为根目录下的 /app.out, 便于后续挂载到主机

最后执行 Docker 构建命令即可

cd /data/app
docker build -t springboot:0.0.1 .
$ docker image ls
REPOSITORY                         TAG        IMAGE ID       CREATED          SIZE
springboot                         0.0.1      8fb90321f02a   35 minutes ago   351MB
mysql                              8.0.33     91b53e2624b4   10 days ago      565MB
redis                              7.0.11     8e69fcb59ff4   11 days ago      130MB
nginx                              1.25.1     eb4a57159180   11 days ago      187MB
bellsoft/liberica-openjdk-centos   17.0.7-7   a403bffd6492   2 months ago     315MB

运行容器

首先需要手动创建一个 app.out 文本文件, 用于挂载容器中的日志文件( docker run 命令创建出来的是目录而不是文件). 容器成功启动后, 通过浏览器访问测试功能是否正常

# 创建 app.out 日志文件
touch app.out
# 创建并启动容器
docker run -d -p 8080:8080 --name springboot -v /data/app/app.out:/app.out springboot:0.0.1
$ docker container ls -a
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
4294184d06b9   springboot:0.0.1   "java -jar /app.jar …"   35 minutes ago   Up 35 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp              springboot
3375183423ad   mysql:8.0.33       "docker-entrypoint.s…"   4 days ago       Up 58 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
6e632edb65c2   nginx:1.25.1       "/docker-entrypoint.…"   5 days ago       Up 58 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp                      nginx
d0c1d9710a52   redis:7.0.11       "docker-entrypoint.s…"   5 days ago       Up 58 minutes   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp              redis

此时, 在浏览器访问 http://ip:8080/index/query 即可获得正确的响应了

如果运行容器报类似如下错误, 则说明在 Docker 运行过程中, 修改过防火墙配置, 从无到有或从有到无, 重启下 Docker 就好了

docker: Error response from daemon: driver failed programming external connectivity on endpoint springboot (b16ca1645c7cdbea5faa70d91f909a72e8a389e8d2714826b6fb336c1e9dfd5f):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8080 -j DNAT --to-destination 172.17.0.5:8080 ! -i docker0: iptables: No chain/target/match by that name.
# 重启 Docker
systemctl restart docker
# 启动所有容器
docker start $(docker ps -aq)

反向代理

Nginx 配置文件添加如下配置

location /springboot/ {
    proxy_pass http://localhost:8080/;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

重启 Nginx 镜像或进入到 Nginx 容器内重载配置文件, 本来访问 http://ip:8080/index/query , 现在改成访问 http://ip/springboot/index/query 了, 实现了反向代理

# 进入 Nginx 容器
docker exec -it nginx /bin/bash
# 测试配置文件
nginx -t
# 重载配置文件
nginx -s reload

结果, 在浏览器访问地址时报 502 … 这就对啦, 在 Nginx 容器里配置的 localhost 和 127.0.0.1 都相当于是该容器自身, Nginx 容器里是没有 Java Web 服务的, 该服务在容器 springboot 中, 所以 Nginx 内部转发请求时会报 502, 我们需要将转发的 IP 地址指向 容器 springboot 即可

# 查看容器信息
docker inspect springboot

通过上述命令查看容器 springboot 的网络设置中的 IPAddress172.17.0.2, 我们将 Nginx 配置更新一下并重新载入配置, 测试访问成功

location /springboot/ {
    proxy_pass http://172.17.0.2:8080/;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

优化

配置可以分环境, 本地配置用公网地址, 不同主机间的容器通信使用内网地址, 同一台主机内的容器通信使用 Docker 给各容器分配的地址, 然后在 Dockerfile 的 ENTRYPOINT 指令最后添加一个参数 --spring.profiles.active=production 来指定应用使用哪套配置即可

常用 Docker 指令

systemctl start docker
systemctl stop docker
systemctl restart docker
docker version # 查看 Client 和 Server 版本信息
docker info # 查看系统信息
docker inspect 镜像/容器/网络/卷 # 查看 Docker 对象的信息
docker login -u mrathena
docker logout
docker push mrathena/test:1.0.0
docker search nginx
docker images
docker pull nginx
docker pull nginx:1.25.1
docker rmi nginx
docker run -d -p 3306:3306 --name mysql -v /data/mysql/data:/var/lib/mysql -v /data/mysql/my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=Mrv587.. mysql:8.0.33
docker rm -f mysql
docker start $(docker ps -aq) # 启动所有容器
docker image list
docker image inspect nginx:1.25.1
docker image pull nginx:1.25.1
docker image save -o nginx.tar nginx:1.25.1
docker image load -i nginx.tar
docker image build -t springboot:1.0.0 .
docker image history nginx:1.25.1
docker image remove -f nginx:latest
docker container list -a
docker container list -aq
docker container inspect nginx
docker container run -d -p 3306:3306 --name mysql -v /data/mysql/data:/var/lib/mysql -v /data/mysql/my.cnf:/etc/mysql/conf.d/my.cnf -e MYSQL_ROOT_PASSWORD=Mrv587.. mysql:8.0.33
docker container start nginx
docker container stop nginx
docker container restart nginx
docker container exec -it mysql /bin/bash
docker container exec -it mysql mysql -u root -p
docker container exec -it redis redis-cli
docker container logs nginx
docker container cp nginx:/etc/nginx/nginx.conf /data/nginx.conf
docker container cp /data/nginx.conf nginx:/etc/nginx/nginx.conf

猜你喜欢

转载自blog.csdn.net/mrathena/article/details/131299849