Docker五部曲之五:通过Docker和GitHub Action搭建个人CICD项目

文章目录

  • 项目介绍
  • Dockerfile解析
  • compose.yml解析
    • Nginx反向代理到容器以及SSL证书设置
    • MySQL的准备工作
    • Spring和环境变量的交互
  • GitHub Action解析
  • 项目测试
  • 结语

项目介绍

该项目是一个入门CICD-Demo,它由以下几部分组成:

  • Dockerfile:用于构建自定义镜像
  • compose.yml:用于搭建应用程序依赖环境并部署
  • deploy.yml:通过GitHub Actions连接腾讯云服务器并构建环境

通过这个Demo,你可以:

  • 从开发到部署所需的所有操作全部都在本地定义完成
  • 不需要在服务器上手动安装任何软件即可完成部署
  • 每次在代码合并到master时自动完成构建和部署

项目地址:CICD-Blog
测试网址:www.ningyu.ink

在这里插入图片描述

Dockerfile解析

这个Dockerfile分为四个构建阶段:

  • base:构建基础镜像
  • dev:构建开发环境镜像
  • build:打包
  • prod:构建生产环境镜像
# syntax=docker/dockerfile:1FROM eclipse-temurin:17-jdk-jammy as base
WORKDIR /blog
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN chmod +x mvnw
RUN ./mvnw dependency:resolve
COPY src ./srcFROM base as dev
EXPOSE 8080
RUN chmod +x mvnw
CMD ["./mvnw", "spring-boot:run"]FROM base as build
RUN ./mvnw packageFROM eclipse-temurin:17-jre-jammy as prod
EXPOSE 8080
COPY --from=build /blog/target/blog-*.jar /blog.jar
CMD ["java", "-jar", "/blog.jar"]

compose.yml解析

该文件包含两个profiles:

  • dev:开发环境,可使用docker compose --profiles dev up -d --build在本地运行
  • prod:生产环境:可使用docker compose --profiles prod up -d --build在服务器运行
services:blog-dev:build:context: .target: devcontainer_name: blogports:- "8080:8080"environment:- MYSQL_URL=jdbc:mysql://mysql/blog?serverTimezone=Asia/Shanghaivolumes:- ./:/blognetworks:mysql-net:depends_on:- mysql-devprofiles:- devblog-prod:build:context: .target: prodcontainer_name: blogenvironment:- MYSQL_URL=jdbc:mysql://mysql/blog?serverTimezone=Asia/Shanghaivolumes:- ./:/blognetworks:mysql-net:nginx-net:depends_on:- mysql-prodprofiles:- prodmysql-dev:image: mysql:8.0container_name: mysqlports:- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=123456- MYSQL_DATABASE=blogvolumes:- mysql_data:/var/lib/mysql- mysql_config:/etc/mysql/conf.d- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sqlnetworks:mysql-net:profiles:- devmysql-prod:image: mysql:8.0container_name: mysqlenvironment:- MYSQL_ROOT_PASSWORD=123456- MYSQL_DATABASE=blogvolumes:- mysql_data:/var/lib/mysql- mysql_config:/etc/mysql/conf.d- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sqlnetworks:mysql-net:profiles:- prodnginx-dev:image: nginxcontainer_name: nginxports:- "80:80"- "443:443"environment:- NGINX_HOST=ningyu.ink- NGINX_PORT=80volumes:- ./nginx/templates:/etc/nginx/templates- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro- ./nginx/ssl:/etc/nginx/sslnetworks:nginx-net:profiles:- devnginx-prod:image: nginxcontainer_name: nginxports:- "80:80"- "443:443"environment:- NGINX_HOST=ningyu.ink- NGINX_PORT=80volumes:- ./nginx/templates:/etc/nginx/templates- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro- ./nginx/ssl:/etc/nginx/sslnetworks:nginx-net:profiles:- prodvolumes:mysql_data:mysql_config:networks:mysql-net:driver: bridgenginx-net:driver: bridge

Nginx反向代理到容器以及SSL证书设置

Nginx的所有配置都在项目下的nginx目录下并通过三个挂在绑定挂载到了容器中:

在这里插入图片描述
其中:

  • ssl:用于存放SSL证书
  • templates:用于存放前端代码
  • nginx.conf:用于自定义配置

由于本项目还没有前端代码,所以在访问时直接代理到了后端接口,具体配置如下:

http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;server {listen 443 ssl;server_name ningyu.ink;ssl_certificate  /etc/nginx/ssl/ningyu.ink_bundle.crt;ssl_certificate_key /etc/nginx/ssl/ningyu.ink.key;ssl_session_timeout 5m;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;ssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers on;location / {proxy_pass http://blog:8000/test/log;}}server {listen       80;server_name  ningyu.ink;return 301 https://$host$request_uri;}
}

其中我们将80端口转发到了443端口,并且在配置文件中可以直接使用容器名称进行网络代理(前提是在同一网络下):

在这里插入图片描述

MySQL的准备工作

MySQL的compose.yml构建语法是这样的:

  mysql-prod:image: mysql:8.0container_name: mysqlenvironment:- MYSQL_ROOT_PASSWORD=123456- MYSQL_DATABASE=blogvolumes:- mysql_data:/var/lib/mysql- mysql_config:/etc/mysql/conf.d- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sqlnetworks:mysql-net:profiles:- prod

它做了以下事情:

  • 传递了两个环境变量:
    • MYSQL_ROOT_PASSWORD指定了root密码
    • MYSQL_DATABASE指定了容器运行后需要创建的数据库
  • 绑定了三个卷:其中第三个指定了一个在项目目录/sql/init.sql的初始化脚本,该脚本用于在数据库中创建应用需要的表

Spring和环境变量的交互

可以看到application.yml内容是这样的:

server:port: 8080spring:application:name: blogdatasource:username: ${MYSQL_USER:root}password: ${MYSQL_PASSWORD:123456}url: ${MYSQL_URL:jdbc:mysql://localhost/blog?serverTimezone=Asia/Shanghai}driver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/*.xml

其中通过${}读取的环境变量值都是在compose.yml中定义的,这极大增强了灵活性。

GitHub Action解析

GitHub Action通过.github/workflows下的deploy.yml起作用,其文件内容是这样的:

name: Deploy
on:push:branches:- master
jobs:deploy:runs-on: ubuntu-lateststeps:- name: Deploy to tencent serveruses: appleboy/ssh-action@v1.0.3with:host: ${{ secrets.REMOTE_HOST}}key: ${{ secrets.SERVER_SSH_KEY }}username: ${{ secrets.REMOTE_USER }}script: |# 切换到主目录cd ~ || exit# 判断是否安装了Docker,如果没有则使用官方提供的脚本安装Dockerif ! command -v docker &> /dev/null ; thencurl -fsSL https://get.docker.com -o get-docker.shsh get-docker.shfi# 判断是否拉拉取了代码,没有拉取则拉取if [ ! -d "./blog" ]; thengit clone https://github.com/chinesecooly/blog.gitfi# 进入工作目录cd blog || exit# 更新代码git pull# 运行prod环境下的构建,并且每次都重新构建镜像docker compose --profile prod up -d --build

它的作用如下:

  • 当向master分支推送代码时就自动运行该action
  • 使用了一个别人定义好的action(appleboy/ssh-action@v1.0.3)通过ssh连接到了腾讯云服务器,这个action需要三个参数(with语句中指定的),这三个参数存储在以下位置,需要根据自己的服务器配置。
    在这里插入图片描述
  • 最后与执行了一个Shell脚本,该脚本有以下功能:
    • 首先检查服务器上是否安装了Docker,如果没安装则下官方提供的Shell脚本进行安装
    • 再检查是否拉取了代码,如果没拉取则拉取
    • 然后进入项目目录并更新代码
    • 最后使用docker compose --profile prod up -d --build命令部署项目,--profile选项指定了选取的profile-d选项指定了容器在后台运行,--build选项指定了每次运行这条指令时都重新构建镜像,这保证了我们每次更新的代码都能署到服务器上

项目测试

以下Controller是该项目提供的一个测试Controller,他完成了一次接收请求、操作数据库、做出响应的过程:

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate TestMapper testMapper;@GetMapping("/log")public Result log() {Test test = new Test();test.setMsg("a get request");test.setData(LocalDateTime.now());testMapper.insert(test);return Result.success(test);}
}

项目部署后访问一下是这样的:

在这里插入图片描述

我们在dev修改一下代码:

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate TestMapper testMapper;@GetMapping("/log")public Result log() {Test test = new Test();test.setMsg("a get request after one push");test.setData(LocalDateTime.now());testMapper.insert(test);return Result.success(test);}
}

合并到master并推送,等待几秒再次访问一下:

在这里插入图片描述

以下是GitHub Actions两次执行的记录:

在这里插入图片描述

结语

通过本文你可以扩展更复杂的应用场景,如有不明白或建议,可留言联系我,如果可以的话点个关注,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/241289.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

像操作本地文件一样操作linux文件 centos7环境下samba共享服务搭建详细教程

1.安装dnf yum -y install dnf 2.安装samba dnf install samba -y 3.配置 3.1创建并设置用户信息 #创建用户 useradd -M -s /sbin/nologin samba echo 123|passwd --stdin samba mkdir /home/samba chown -R samba:samba /home/samba smbpasswd -a samba smaba设置密码示…

Dobbo --- HelloWorld项目搭建

Dobbo-HelloWorld 1. demo -- spring方式集成1.1 实现步骤 2. demo -- springboot方式集成2.1 实现provider2.2 实现consumer2.3 项目测试 1. demo – spring方式集成 dubbo官方文档 提供一个可被调用的接口 提供方:实现接口的方法逻辑,启动应用程序&a…

跨境电商多语种服务指南:如何提供优质的客户体验?

卓越的客户支持是成功企业的核心,客户希望得到全天候的及时响应。根据《哈佛商业评论》的研究报告,快速及时地响应会促使人们在未来支付更多的费用。而在与全球客户打交道时,特别是跨境电商企业,您的沟通必须超越语言障碍。用客户…

Python爬虫 - 网易云音乐下载

爬取网易云音乐实战,仅供学习,不可商用,出现问题,概不负责! 分为爬取网易云歌单和排行榜单两部分。 因为网页中,只能显示出歌单的前20首歌曲,所以仅支持下载前20首歌曲(非VIP音乐&…

【笔记】Helm-3 主题-6 Chart仓库指南

Chart仓库指南 本节介绍如何创建和使用chart仓库。在高层级中,chart仓库是打包的chart存储和分享的位置。 社区的Helm chart仓位于 Artifact Hub ,欢迎加入。不过Helm也可以创建并运行您自己的chart仓库。该指南将介绍如何操作。 Artifact Hub 先决条…

C语言之编译和链接

目录 一、引言 二、编译和链接 2.1 预处理&#xff08;预编译&#xff09; 2.2 编译 2.3 汇编 2.4 链接 一、引言 #include <stdio.h> int main() {printf("hello, world\n");return 0; } 像这样&#xff0c;只由ASCII字符构成的文件被称为文本文件&…

java结合百度ocr实现图片文字提取功能

1.进入百度云控制台&#xff0c;找到文字识别服务&#xff0c;创建一个应用 2.引入ocr需要的maven依赖包 <dependency><groupId>com.baidu.aip</groupId><artifactId>java-sdk</artifactId><version>4.16.11</version> </depend…

go实现判断20000数据范围内哪些是素数(只能被1和它本身整除的数),采用多协程和管道实现

实现一个并发程序&#xff0c;用于寻找 20000 以内的所有素数。使用了 Goroutines 和 Channels 来分发和处理任务&#xff0c;并通过 WaitGroup&#xff08;实现为 exitChan&#xff09;来同步 Goroutines 的退出。 一.GO代码 package mainimport ("fmt""time…

C++初阶类与对象(三):详解复制构造函数和运算符重载

上次介绍了构造函数和析构函数&#xff1a;C初阶类与对象&#xff08;二&#xff09;&#xff1a;详解构造函数和析构函数 今天就来接着介绍新的内容&#xff1a; 文章目录 1.拷贝构造函数1.1引入和概念1.2特性 2.赋值运算符重载2.1运算符重载2.2放在哪里2.3运算符重载示例2.3.…

深度学习(1)--基础概念

目录 一.计算机视觉(CV) 二.神经网络基础 三.神经网络整体架构 一.计算机视觉(CV) (1).计算机视觉中图像表示为三位数组&#xff0c;其中三维数组中像素的值为0~255&#xff0c;像素的值越低表示该点越暗&#xff0c;像素的值越高表示该点越亮。 (2).图像表示 A*B*C&#xf…

美摄视频SDK的HDR格式编辑方案

在当今的视觉媒体时代&#xff0c;高动态范围&#xff08;HDR&#xff09;技术已成为高质量视频内容的标配。为了满足企业对高效、高质量视频处理的需求&#xff0c;美摄科技推出了业界领先的视频SDK&#xff0c;全面支持多种HDR标准的图像视频进行处理。 一、核心优势 HDR全…

视频智能识别周界入侵检测AI智能分析网关V4如何配置ONVIF摄像机接入

AI边缘计算智能分析网关V4性能高、功耗低、检测速度快&#xff0c;易安装、易维护&#xff0c;硬件内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。算法可按需组合、按…

从matlab的fig图像文件中提取数据

这里用的是openfig&#xff08;&#xff09;函数打开的fig文件 →→→【matlab 中 fig 数据提取】 很简洁 →→→【MATLAB提取 .fig 文件中的数据】 这个给出了包含多个曲线的情况 →→→【提取matlab fig文件里的数据和legend】 chatgpt给出的方法 打开fig文件并保存数据 我的…

Vue入门七(Vuex的使用|Vue-router|LocalStorage与SessionStorage和cookie的使用|路由的两种工作模式)

文章目录 一、Vuex1&#xff09;理解vuex2&#xff09;优点3&#xff09;何时使用&#xff1f;4&#xff09;使用步骤① 安装vuex② 创建vuex③ 导入vuex④ 创建仓库Store⑤ 基本使用 5&#xff09;五个模块介绍1.State2.mutations3.actions4.Getter5.Modules 6&#xff09;购物…

QT设置QTableWidget左上角文字(CornerButton)

关于这个左上角 在QTableWidget中&#xff0c;左上角有一个可以点击的空白区域&#xff0c;如图&#xff1a; 默认情况下&#xff0c;点击它会全选所有的单元格。 它即不属于列表头&#xff0c;也不属于行表头&#xff0c;它的名称叫Corner Button 在QTableWidget中&#xf…

Flask 项目怎么配置并创建第一个小项目?附上完成第一个小案例截图

目录 1. 为什么要学习 flask&#xff1f; 2. flask 是什么&#xff1f; 3. flask 如何使用&#xff1f; 要安装 Flask&#xff0c;可以按照以下步骤进行&#xff1a; 4. 使用流程 4.1. 新建项目 4.1.1. 打开 pycharm&#xff0c;新建项目 4.1.2. 设置目录&#xff0c;并…

【JavaEE进阶】 依赖注⼊DI详解

文章目录 &#x1f334;什么是依赖注入&#x1f384;依赖注入的三种方法&#x1f6a9;属性注⼊(Field Injection)&#x1f6a9;构造⽅法注⼊&#x1f6a9;Setter注⼊&#x1f6a9;三种注⼊的优缺点 &#x1f333;Autowired存在的问题&#x1f332;解决Autowired存在的问题&…

借势营销怎么做才能有效宣传?媒介盒子揭秘

借势营销之所以受到品牌欢迎&#xff0c;原因就在于通过借势营销能够达到“润物细无声和四两拨千斤的效果&#xff0c;用小投入获得大回报&#xff0c;但有许多企业稍有不慎就会翻车&#xff0c;今天媒介盒子就从多个角度和大家聊聊&#xff1a;借势营销怎么做才能有效宣传。 一…

深入详解使用 RabbitMQ 过程中涉及到的多个细节问题(面试可用)

目录 1、基础类问题 2、cluster 相关问题 3、综合性问题 4、参考资料 C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/125529931C/C基础与进阶&…

如何隐藏服务器真实IP地址,隐藏服务器IP有什么好处

首先我们介绍了隐藏服务器IP的概念及工作模式&#xff0c;接着阐述了其对于DDoS攻击的防护作用。然后介绍了如何利用隐藏服务器IP增加系统性能和稳定性。接着我们讲述了如何隐藏服务器IP防止黑客攻击&#xff0c;最后总结了隐藏服务器IP在保护服务器和用户数据方面发挥的作用。…