简介
因为一个小项目,之前一直是手动制作镜像,现在需要用docker部署,然后还要基于arm64编译,想着不如实践一下,学习一下github action和Dockerfile的编写。
Dockerfile篇
Dockerfile是可以通过docker提供的最小系统镜像,通过编写指令可以自动配置运行/编译环境,避免之前每次发布一个版本就得手动pull系统自己安装环境和导入项目程序的无意义劳动。
在Dockerfile中配置主要以COPY 和RUN指令为主,COPY可以复制工作目录的文件到容器下,而RUN就是在容器里执行指令。注意每一行RUN都会为增加镜像的深度,所以不必要的步骤可以尽可能的写在一个RUN中。
为了让最终运行的镜像尽可能小,在Dockerfile中可以指定两个独立容器,一个编译用,一个是运行环境。代码如下,对应的解释都放在了注释里了
#编译用镜像,起名为builder
FROM alpine:3.16 as builder
#指定工作目录,容器下只有该目录的文件会保留
WORKDIR /networkmanager/
#复制项目文件到容器内
COPY ./ /networkmanager/
#为编译环境安装完整的编译包支持
RUN apk update && apk add openssl gcc g++ make libffi-dev openssl-dev libtool cmake
#编译目标程序
RUN cmake . && make
#至此该容器下已经得到了可执行程序
#主镜像
FROM alpine:3.16
LABEL org.opencontainers.image.authors="wmdscjhdpy@gmail.com"
#设置环境变量
ENV username=enteryournumber
ENV interval=30
#设定工作目录
WORKDIR /networkmanager/
#为运行环境安装运行必须的库即可
RUN apk update && apk add openssl libgcc libstdc++ binutils
#只需要从builder镜像中获取二进制文件而不需要源代码
COPY --from=builder /networkmanager/network .
#声明一个卷,声明后卷文件独立于容器本身,即便容器崩了数据也还在
VOLUME /etc/networkmanager/
#设置容器入口程序
ENTRYPOINT ["/networkmanager/network"]
这种编写方式就分离了编译镜像和执行镜像,同时linux发行版选择最小的alpine可以尽可能的压缩镜像大小,可以看到最终镜像才几兆。
Dockerfile编写完后可以测试一下是否可以正常build,完事后就进到了下一个环节
Github Action 篇
github action 可以利用特定的触发器,来让github设置当代码更新时,自动生成对应的docker image。github提供了很多模块化的自动任务,我们只需要将这些任务拼接起来。
这里我们使用的模块有:导入仓库,多平台image生成用的QEMU和buildx,dockerhub的自动登录,自动build和push,这些模块都只需要简单看一下描述,给出关键参数即可。实际上就是拼积木
我的action源码如下,对应部分给出了注释:
name: Docker Image CI
#触发器设置
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
#项目任务,任务之间可以并行调度
jobs:
build:
#选择云端运行的环境
runs-on: ubuntu-latest
steps:
#uses代表使用一个模块,此处使用的是checkout模块,将github项目文件导入到当前环境中
- uses: actions/checkout@v3
#使用with跟在后面来为前面的模块输入参数
with:
submodules: 'true'
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
#这里用到了github的secrets功能,避免账户和密码随仓库泄露
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
#导入这个模块来完成自动编译和推送
uses: docker/build-push-action@v3
with:
context: .
push: true
#在这里通过加入需要编译的平台和前面配好的QEMU,buildx来达到多平台编译
platforms: linux/amd64,linux/arm64,linux/arm
#指定用户/仓库名
tags: wmdscjhdpy/test:latest
- name: Docker Hub Description
#这里是通过md文件自动生成dockerhub描述的模块,也可以不需要
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
repository: wmdscjhdpy/autologin
readme-filepath: ./doc/docker-readme.md
通过这样一个搭积木,传参数的方式,就达到了每次提交时就完成这样一系列的任务。但这其中还存在着secrets的秘密参数,可以通过在github项目的settings->Security->Secrets->Actions,通过创建Repository secrets来完成输入秘密参数,其中dockerhub的token需要在dockerhub网站上自己生成。
这样一来,就大功告成了!只要仓库有新的提交,dockerhub上也会随之生成可用的最小image!