CentOS 7.6 + Docker20 服务器部署记录
00. 前置说明
本案例使用 XShell 7 远程连接 CentOS 服务器,其中的一些操作说明如下:
CTRL + INSERT
复制SHIFT + INSERT
粘贴vi / vim
使用文本编辑器- 其中,按
a
/i
/o
可以进入插入(INSERT)模式开始编辑。 - 按
ESC
退出编辑模式,回到命令模式,可以进行文件保存和退出操作。 - 在命令模式下输入
:wq
保存退出,输入:q!
不保存强制退出。 - 详细操作可以参考 https://blog.csdn.net/sinat_33479559/article/details/81988515
- 其中,按
mv
文件(夹)移动
01. 搭建环境
服务器采用容器化部署,将 MySQL:8.0.29,nginx,以及 jar 包分别安装于对应的一个容器 container
之中,容器由镜像 image
制作而成。
因此,常见的步骤是先拉取一个镜像,再使用镜像制作容器。
1.在 CentOS 中下载 jdk 17
参考链接:https://blog.csdn.net/chenshm/article/details/124358714
# 下载压缩包
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
# 解压
tar xf jdk-17_linux-x64_bin.tar.gz
# 新建目标文件夹并将解压后的文件夹移动过去
mkdir -p /usr/lib/jvm && mv jdk-17.0.4.1 $_
# 配置环境变量
vi /etc/profile
# 添加下面的内容
export JAVA_HOME=/usr/lib/jvm/jdk-17.0.4.1
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
# 刷新环境变量
source /etc/profile
# 验证安装
java -version
2.创建 mysql:8.0.29 容器
# 拉取 mysql 对应版本的镜像
docker pull mysql:8.0.29
# 通过镜像创建一个容器
# 设置端口为 映射本机 3306 端口至容器的 3306 端口
# 容器名称为 localhost 以便后续 jar 包容器连接
# 密码需要填入
docker run -itd -p 3306:3306 --name localhost \
-e MYSQL_ROOT_PASSWORD=[password] mysql:8.0.29
# 加入 mysql 容器内,配置 mysql
docker exec -it localhost bash
mysql -u root -p
# 输入密码
use mysql;
# mysql 8+ 设置允许访问,记得先填入密码
create user root@'%' identified by '[password]';
grant all privileges on *.* to root@'%' with grant option;
# 刷新
flush privileges;
# 退出 mysql
exit;
# 退出容器
exit;
踩坑点:
- mysql 8+ 的开放权限的方式与过去的版本不太一样,如果并非 mysql 8+ 的版本可以自行搜索对应版本的权限设置方式。
- 此时可以在 navicat 上尝试连接自己的数据库,如果连接不成功,可能是防火墙设置没有开放
3306
端口!
3.创建 nginx 容器
这里 nginx 用于进行反向代理,动静分离(静态资源与 api 接口分开)以及ssl 证书配置。
由于进入 nginx 容器频繁修改配置可能较为麻烦(其实不太了解具体的步骤,有兴趣的可以自行尝试),本案例采用的是:
- 先在本机创建编辑配置文件,然后在创建容器的时候,再将本机的配置文件映射(复制)到容器之中。
- 需要先创建一个临时的 nginx 容器,并将容器中的默认配置文件复制到本机,在此基础上进行修改。
踩坑点:
- 需要特别注意的是,此后如果再次修改位于本机的配置文件,需要 重新生成 nginx 容器 。即将新的配置文件复制到新的容器之中。
- 如果要配置开放静态资源的访问,一定要将 本机中静态资源所在的文件夹 映射到 容器之中。
# 在本机新建文件夹,即后续将映射到容器中的文件
mkdir -p /home/nginx/conf # 配置文件
mkdir -p /home/nginx/cert # 证书
mkdir -p /home/nginx/log # 日志
mkdir -p /home/nginx/html # 默认 html
# 创建临时容器
docker run --name nginx -p 80:80 -d nginx
# 将容器中的 nginx.conf 文件复制到宿主机
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
# 将容器中的 conf.d 文件夹下内容复制到宿主机
docker cp nginx:/etc/nginx/conf.d /home/nginx/conf/conf.d
# 将容器中的 html 文件夹复制到宿主机
docker cp nginx:/usr/share/nginx/html /home/nginx/
① 修改 nginx 配置:
本案例默认需要进行 ssl 配置,无需配置 ssl 的可以略过下面的上传步骤和 nginx 配置文件中监听 443 端口的 server 块。
上传 ssl
证书至对应的目录:
需要上传 crt
后缀的证书 和 key
后缀的私钥文件。
# 进入证书目录
cd /home/nginx/cert
# 上传文件,如果提示 rz 不是一个命令 可以搜索一下报错信息,网上应该有很多解决方法
rz -be
修改 nginx
的配置文件:
# 通过编辑器打开配置文件,如果有提示文本,需要按几次回车才能进入
vi /home/nginx/conf/nginx.conf
下面是 nginx 的配置文件:
- 其中 server 块中的
server_name
填写自己网站的域名或者 ip。 ssl_certificate
/ssl_certificate_key
将abc.com.crt
修改为自己的证书的文件名。
# 配置 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;
#gzip on;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
# 修改域名
server_name abc.com;
# http 重定向至 https
rewrite ^ https://$http_host$request_uri? permanent;
}
server {
listen 443;
# 修改域名
server_name abc.com;
ssl on;
# 修改为自己的证书文件名字
ssl_certificate /etc/nginx/cert/abc.com.crt;
ssl_certificate_key /etc/nginx/cert/abc.com.key;
ssl_session_timeout 5m;
# 开放静态资源,具体配置可以搜索一下
location /img/ {
root /public/;
}
# 反向代理至 api 接口
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# 注意这里,后续可能需要修改为 jar 包容器所在的本地 ip 地址
proxy_pass http://172.17.0.3:8080/;
proxy_redirect off;
}
}
}
② 制作 nginx 容器并运行
如果需要开放访问静态文件夹的,需要在最后的 -v 下面添加一行
如 -v /public:/public
将本机的静态资源文件夹映射到容器中
否则会出现 404 Not Found
错误!
后续进行 nginx 配置文件修改,只需要重新执行下面的脚本重新生成容器即可。
docker run \
-p 80:80 \
-p 443:443 \
--restart=always \
--name nginx \
-v /home/nginx/cert:/etc/nginx/cert \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/conf/conf.d:/etc/nginx/conf.d \
-v /home/nginx/log:/var/log/nginx \
-v /home/nginx/html:/usr/share/nginx/html \
-d nginx
02. 部署 jar 包
我们需要将 jar 包制作为一个镜像,并以此创建一个容器。
第一次部署 jar 包的步骤如下,后文再具体讲述更新步骤。
1. 上传 jar 包
选择一个目录存储 jar 包并进入该目录。
# 上传
rz -be
2. 编写 Dockerfile
可以复制下面的文本相应编辑后保存为 Dockerfile
(无后缀),并上传到 jar 包所在目录。
或者直接通过 XShell 在 jar 包所在的目录输入 vi Dockerfile
命令创建 Dockerfile
文件,进行编辑。
修改 ADD 行和 CMD 行的 jar 包名字
ADD [目录下的jar包名字].jar /[容器中的 jar 包名字(自定义)].jar
CMD ["java","-jar","[容器中的 jar 包名字].jar" ]
FROM openjdk:17
VOLUME /tmp
ADD bounty-task-0.0.1-SNAPSHOT.jar /bounty-task.jar
EXPOSE 80
ENV JAVA_HOME /usr/lib/jvm/jdk-17.0.4.1
ENV PATH $PATH:$JAVA_HOME/bin
CMD ["java","-jar","bounty-task.jar"]
3. 制作容器
在 jar 包和 Dockerfile 所在的目录执行下列的命令:
# 通过 Dockerfile 创建一个镜像
# 镜像名为 bountytask,可以自行修改
# 注意最后有一个点
docker build -t bountytask .
# 通过 bountytask 镜像制作一个容器
# -restart=always 自动重启
# -name bountytask 容器名
# -p 本机的 8080 端口映射到容器的 8080 端口
# -link localhost:localhost 连接 MySQL 容器
# 最后一个参数为镜像名
docker run -itd \
--restart=always \
--name bountytask \
-p 8080:8080 \
–link localhost:localhost \
bountytask
可以先重启一次 docker:由于之前的容器都设置了 --restart=always
因此会自动随着 docker 启动而启动。
systemctl restart docker
然后通过 docker ps
可以查看正在运行的 docker 容器及其端口号。
这里如果 STATUS
显示 Restarting
可能是 jar 包有问题。
可以通过 docker logs [容器名]
可以查看 jar 包运行日志。
查看 jar 包容器的实际 ip 地址:
docker inspect -f '{
{range .NetworkSettings.Networks}}{
{.IPAddress}}{
{end}}' bountytask
本案例是 172.17.0.4
,需要修改之前的 nginx 的配置文件中请求转发的 ip 地址及端口号 proxy_pass
,这里的端口号为上文 制作 jar 包容器 时映射的端口号(本案例为 8080
)。
然后重新制作 nginx 容器(参见上文):
vi /home/nginx/nginx.conf
4. 测试接口
03. jar 包更新
jar 包更新,相当于上述 02 中的上传 jar 包 + 制作容器,因为 Dockerfile 是可以复用的。
① 上传新的 jar 包
其中,上传新的 jar 包前,要将原先同名的 jar 包删除:
rm -rf [jar包名]
rz -be
② 清除旧容器 & 镜像,根据新的 jar 包制作新的镜像 & 容器
这里顺序需要注意:
一定是先清除容器,才能清除镜像。
而制作时需要先制作镜像,才能制作容器。
由于 jar 包需要频繁更新,因此,可以将上面的制作镜像和容器的命令写成一个脚本,方便进行替换。
update.sh
脚本如下,具体配置自行修改,然后上传到 jar 包所在的目录:
#!/bin/bash
# 这里修改为镜像的名字(=容器的名字)
jarName=bountytask
function clear_old_container {
echo "################## 正在清除旧容器... ####################################"
docker stop $jarName
docker rm $jarName
}
function clear_old_image {
echo "################## 正在清除旧镜像... ####################################"
docker image rm -f $jarName || true
}
function build_image {
echo "################## $1 镜像构建中... ####################################"
echo "$1 image building..."
docker build -t $1 $2
}
clear_old_container
clear_old_image
build_image $jarName .
# 制作 jar 包容器,具体配置需要自行修改
docker run -itd --restart=always --name $jarName -p 8080:8080 --link localhost:localhost $jarName
echo "$jarName image runing..."
echo "############## 部署完成 ############################"
由于脚本文件中存在一些换行符,会导致运行出错,因此需要先将那些换行符替换掉:
# 上传 update.sh 至服务器,需要先将换行符转换掉
sed 's/\r//' update.sh>update2.sh
# 转换后的 update2.sh 重命名为 update.sh,覆盖原先的
mv update2.sh update.sh
运行 update.sh
即可进行容器更新:
bash update.sh
04. 后话
半瓶水的前端第一次接触服务器相关的东西,踩了很多坑,可能容器架构的也不是很合适,特别是 jar 包与 MySQL 通信这里,因为时间的原因也没有继续深究下去。
如果大家有遇到什么问题或者有好的建议,欢迎在评论区一起探讨。