[CI/CD] 从实例到 DooD 部署的流程(特点:Nginx、Jenkins)
使用 Docker 和 Nginx 巩固部署基础
23-06-16 修改路径,使音量安装更清晰 23-07-05 调整设置,方便开发
简介
[CI/CD]使用 Docker + Jenkins + Git Webhook 组织 FastAPI 服务器的自动部署
之所以写这篇文章,是因为上面的最后一篇文章包含了我当初努力学习的内容,但我想把需要修正的部分修正一下,把需要打磨的部分打磨一下,完成成一篇整齐的文章。
从上次开始,我已经掌握了一定的诀窍,并将部署任务条理化,也帮助了身边的人进行部署,所以我希望可以将其记录下来,作为下次部署的统一流程!如果你按照本帖的顺序进行部署,我想你不会觉得有什么困难。
###第 1 部分后我学到的其他东西
- 为什么要在 Docker 之外而不是 Docker 之中实施?
默认情况下,Docker 不鼓励在 Docker 容器上执行命令。
- Docker 中的 Docker 赋予安装了 Docker 的容器强大的权限,这可能是一个安全风险
- Docker 外的 Docker 允许你通过与容器外的 Docker 共享套接字来运行 Docker 命令。
- 使用 Docker API 如何?
实际上,我就是用它来解决第 1 部分中的问题的,而且成功了。 但我认为,如果你已经成功地从 Docker 中构建了系统,那么在 CI/CD 程序中就不需要它了......
关于应用程序接口的一些内容,我觉得太含糊,无法单独写出来,所以就写下来了。
Docker 使用 REST API 在引擎和客户端之间进行通信,该 API 大部分未被使用,但可用。
docker --tlsverify --tlscacert=/.docker/ca.pem \
--tlscert=/.docker/cert.pem --tlskey=/.docker/key.pem \
-H={server_ip}:{port_number} exec nginx \
sed -i '4s/.*$/ server {container}:8000;/' /etc/nginx/sites-available/default.conf
这段代码通过带有 TLS 证书的 Docker 客户端修改位于任意服务器上的 Nginx 配置文件的内容。 它通过 -H 命令,通过服务器上的端口与守护进程(Docker 引擎)通信,代码的其余部分是通过证书确保访问安全的程序。
如果不使用证书而开放端口,就会有人通过该端口撞毁你的容器!
이미지를 불러올 수 없습니다.
容器干扰的真实体验。我在没有安全认证的情况下打开了一个 Docker 常用的端口...
通过证书确保安全是必须的,如果因为某些不可避免的原因而无法确保安全,就必须限制通过该端口运行的命令。
详情请参见 [Docker应用程序接口文档] (https://docs.docker.com/engine/api/v1.43/)!
构建 All in One 部署基础的步骤
1. 访问和更新实例
ssh -i {secure shell key 경로} {사용자 이름}@{IP 주소}
sudo apt-get update
sudo apt-get upgrade
如果设置的是 ubuntu,用户名通常是 ubuntu。
2. 防火墙设置
sudo ufw allow ssh # ssh를 22로 대체할 수 있다.
sudo ufw allow http # http를 80으로 대체할 수 있다.
sudo ufw allow https # https를 443으로 대체할 수 있다.
sudo ufw enable # 방화벽 가동
sudo ufw status # 방화벽 상태 확인
如果你使用的是云,云默认有自己的端口安全设置,所以需要在设置中单独打开。 UFW 是 Ubuntu 的防火墙,如果第一次设置时关闭了,则需要允许端口后再打开。 通过上述设置,你可以打开防火墙,并默认打开 HTTP(80)、HTTPS(443) 和 SSH(22) 端口。
建议先打开端口允许设置。如果在 SSH 端口 22 关闭的情况下打开防火墙,将无法连接到防火墙。
3. 安装 Docker 和 Docker Compose
# Docker 설치
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Docker Compose 설치
sudo apt install docker-compose
截至 2023 年 5 月,我只从文档中摘录了我需要的内容。
sudo usermod -aG docker $USER
该命令允许你在没有 sudo 的情况下使用 docker 命令。
如果不包含它,你会得到 /var/run/docker.sock: connect: permission denied。
4. 编写 docker-compose.yml
version: '3.8'
networks:
{원하는 네트워크 이름}:
driver: bridge
services:
# Jenkins Container 설정
jenkins:
container_name: jenkins
image: jenkins/jenkins:lts
restart: unless-stopped
ports:
- "{원하는 포트 번호}:8080"
volumes:
- ./mount/jenkins:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
user: root
environment:
- TZ=Asia/Seoul
networks:
- {원하는 네트워크 이름}
部署管道工具的编写方式就像利用 Jenkins 一样。
如果没有需要添加的网络,可以完全省略网络部分,直接从 Docker 中为要使用的套接字进行卷绑定。你可以根据需要设置时区或其他卷绑定。
5. 为要使用的域设置 DNS
不同的域名提供商使用不同的方法。您需要查看域名提供商的注册说明,注册您要使用的服务器的 IP,并将其与您的域名关联起来。
您不能注册后立即开始使用,DNS 服务器会有一个反映时间差。我在上面附上了一个网站,您可以轻松查看它的受欢迎程度。
6. 使用 Let's Encrypt 签发证书
1) docker-compose.yml
# Nginx 설정
nginx:
container_name: nginx
image: nginx:latest
restart: unless-stopped
volumes:
- ./mount/nginx/nginx.conf:/etc/nginx/nginx.conf # Nginx 설정을 위한 바인딩
- ./mount/nginx/sites-available:/etc/nginx/sites-available
- ./data/certbot/conf:/etc/letsencrypt # 인증서 공유를 위한 바인딩
- ./data/certbot/www:/var/www/certbot
ports:
- 80:80
- 443:443
environment:
- TZ=Asia/Seoul
networks:
- {원하는 네트워크 이름}
# Certbot 컨테이너 설정
certbot:
container_name: certbot
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
environment:
- TZ=Asia/Seoul
将此添加到 docker-compose.yml,但不要处理它。
2) mount/sites-available/default.conf
server {
listen 80;
listen [::]:80;
server_name my_domain.org;
location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
}
}
文件,并在其中加入 server_name 后跟上您的域名。
3) mount/nginx.conf
user nginx;
worker_processes auto;
worker_priority 0;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
multi_accept off;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
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"';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log debug;
gzip on;
include /etc/nginx/sites-available/*;
}
这是一个相当基本的配置,基于首次安装nginx时所包含的内容。
4) 通过 Let's Encrypt 签发证书,这是一个过程
curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh -o init-letsencrypt.sh
chmod +x init-letsencrypt.sh
vi init-letsencrypt.sh # 여기서 도메인과 메일 주소를 입력해야 함
sudo ./init-letsencrypt.sh
从外部获取帮助你完成证书签发过程的文件,并设置权限。然后,你可以在文件中输入你的域名和电子邮件地址,并运行文件来签发证书。如果签发失败,你可以查看日志找出失败原因,修复后再试一次。
7. 为证书更新设置 Nginx
# Nginx 설정
nginx:
container_name: nginx
image: nginx:latest
restart: unless-stopped
volumes:
- ./mount/nginx.conf:/etc/nginx/nginx.conf
- ./mount/sites-available:/etc/nginx/sites-available
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- 80:80
- 443:443
environment:
- TZ=Asia/Seoul
networks:
- {연결을 원하는 네트워크 이름}
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
# Certbot 컨테이너 설정
certbot:
container_name: certbot
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
environment:
- TZ=Asia/Seoul
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
Let's Encrypt 签发的证书有效期有限,当证书即将过期时可以重新签发。你可以在 certbot 和 nginx 容器中添加与补发相关的命令,以自动处理证书更新。这样,nginx 就不会因为证书已签发而在构建容器时出错。
8.在 Jenkins 容器内安装 Docker
已添加)我原本直接列出了命令,但我意识到这并不直观,所以我修正了它!
# /jenkins-docker-install.sh
apt-get update
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
我创建了一个 sh 文件,可以从现有的 docker 安装方法中移除 sudo 命令。你可以通过挂载把这个文件放进去,然后运行它,就能实现干净利落的单间安装了!
9. 处理 Docker Compose
version: '3.8'
networks:
{네트워크 이름}:
driver: bridge
services:
# Jenkins Container 설정
jenkins:
container_name: jenkins
image: jenkins/jenkins:lts
restart: unless-stopped
ports:
- "{포트 번호}:8080"
volumes:
- ./mount/jenkins:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- ./mount/jenkins-html:/var/lib/jenkins
- ./jenkins-docker-install.sh:/jenkins-docker-install.sh
user: root
environment:
- TZ=Asia/Seoul
networks:
- {네트워크 이름}
# Nginx 설정
nginx:
container_name: nginx
image: nginx:latest
restart: unless-stopped
volumes:
- ./mount/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./mount/nginx/sites-available:/etc/nginx/sites-available
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- 80:80
- 443:443
environment:
- TZ=Asia/Seoul
networks:
- {네트워크 이름}
depends_on:
- {선행 컨테이너}
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
# Certbot 컨테이너 설정
certbot:
container_name: certbot
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
environment:
- TZ=Asia/Seoul
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
添加这些 Jenkins 配置后,运行
docker-compose -f {yml 파일 위치 및 파일명} up -d
命令调出所有容器。
docker exec -it jenkins bin/bash
sh /jenkins-docker-install.sh
通过在 Jenkins 容器内安装 Docker,我们可以通过 Jenkins 内部 Shell 命令控制 Docker 引擎。 我们遵循了现有的 Docker 文档,但不同之处在于我们没有使用 sudo,而且我们安装的是 Debian 版 Docker。
可选
1. 设置交换内存
# swap memory 설정
sudo fallocate -l {설정 용량} /swapfile # 설정 용량은 대체로 G 단위로 설정한다.
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 재부팅 시에도 지속 사용을 원할 경우
sudo vi /etc/fstab # '/swapfile swap swap defaults 0 0' 내용을 해당 파일에 삽입
# swap 비활성화
sudo vi /etc/fstab # '/swapfile swap swap defaults 0 0' 내용을 제거
sudo swapoff -v /swapfile
sudo rm /swapfile
根据实例性能和需求,您可能需要设置交换内存,以防止实例弹出。
2. 如果 Jenkins 插件安装错误,应尝试哪些方法
<解决方案 1
转到 Jenkins 管理 > 插件管理器 > 高级设置 > 更新站点部分
将 https://updates.jenkins.io/update-center.json 更改为 http://updates.jenkins.io/update-center.json
<解决方案 2
安装名为 skip-certificate-check 的插件
这不是一个完美的解决方案,但我看到所有这些解决方案都取得了一些成功。
结论
关于 Docker,我就写到这里吧,除了稍后的一些框架部署。如果有机会,我以后会写更多关于部署的内容,因为在真实网络上看到自己的工作是一种很棒的感觉。
댓글 작성
게시글에 대한 의견을 남겨 주세요.