中文
[CI/CD] 从实例到 DooD 部署的流程(特点:Nginx、Jenkins)

[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

Ubuntu Docker 安装文件

截至 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 是什么

您不能注册后立即开始使用,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,我就写到这里吧,除了稍后的一些框架部署。如果有机会,我以后会写更多关于部署的内容,因为在真实网络上看到自己的工作是一种很棒的感觉。

댓글 작성

게시글에 대한 의견을 남겨 주세요.

댓글 0