声明:个人所学记录,有可以改进的地方希望不吝指教
Dockerfile
# 使用golang官方镜像作为构建环境
FROM golang:1.23-alpine AS builder
# 设置工作目录
WORKDIR /app
# 设置环境变量镜像变量
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn,direct
# 复制go.mod 和 go.sum文件到工作目录
# Docker 使用层(Layer)的概念来构建镜像。每个指令(比如 COPY、RUN)都会创建一个新层。当某一层的内容发生变化时,这一层以及所有后续层都需要重新构建。
COPY go.mod .
COPY go.sum .
# 下载依赖
RUN go mod tidy
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build --ldflags "-s -w" -o main .
# 使用轻量级的alpine作为运行环境
FROM alpine:latest
WORKDIR /app
# 设置时区为上海 使用阿里云的镜像源
RUN sed -i 's|https://dl-cdn.alpinelinux.org|https://mirrors.aliyun.com|g' /etc/apk/repositories && \
apk update && \
apk add --no-cache tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
apk del tzdata
# 从builder阶段复制编译好的二进制文件
COPY --from=builder /app/main .
# 暴露应用端口(根据你的应用实际端口修改)
EXPOSE 8080
CMD ["./main"]
docker-compose.yml
services:
webshop:
# ${VERSION}是后面自定义的,这里需要带上
image: 阿里云仓库链接/命名空间/镜像仓库:${VERSION}
build:
context: .
dockerfile: Dockerfile
container_name: webshop
# host模式不需要指定端口
# ports:
# - "${SERVER_PORT}:${SERVER_PORT}"
network_mode: host
volumes:
- ./logs:/app/logs
- ./uploads:/app/uploads
- .env:/app/.env
restart: unless-stopped
docker-compose中踩坑的点:
1、时区问题,从数据库获取datetime时取到的一直是UTC,但数据库的时间已经是对的,希望获取的是2025-01-14T21:00:00.000+8:00
而不是2025-01-14T21:00:00.000Z
,尝试更改mysql配置和服务器时间,但问题的根源是我在docker-compose中加了
environment:
- TZ=Asia/Shanghai
导致时区错乱。
2、挂载问题,由于.env文件是 . 开头,所以是隐藏状态,使用ls命令无法查看到文件,可以直接cat .env
输出文件内容查看是否挂载成功。在容器未运行时候由于挂载未生效,此时使用docker run -it 镜像ID sh
查看想挂载的文件是查看不到的,在这卡了很久一直以为未挂载成功。
3、由于配置错误容器无法启动,无法使用docker exec
查看容器内部情况,可以先在docker-compose.yml中加入
command: /bin/sh -c "sleep 1000"
保持程序前台运行后再进入容器查看。
4、使用host模式是因为我使用默认模式时在服务器上无法连接到mysql服务器,不清楚原因但使用host可以连接成功后没有深究。
配置自动化部署,使用Github Actions+阿里云镜像仓库
阿里云部分 Start
首先在阿里云控制台中搜索容器镜像服务
创建个人版实例
创建一个命名空间
创建一个镜像仓库,后续的镜像制品都存在这个仓库中
推送的镜像都在镜像版本中,基本信息中有自己的仓库链接地址,隐私原因不放图了
在访问凭证中设置一个固定密码
阿里云部分 END
Github配置 Start
将密码等隐私信息存储在github中,不明文写在配置中
github actions的yml配置
在项目中建个文件夹.github
,在这个.github
文件夹里面再建一个workflows
文件夹,下方的go.yml存在这里面。
name: 自动化部署
# 当push到master时自动部署,根据个人需要更改
on:
push:
branches: ["master"]
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set_version.outputs.version }} # 添加输出变量,用于传递给其他 job使用
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 配置 Go 环境
uses: actions/setup-go@v4
with:
go-version: '1.23.3'
- name: 设置部署时间戳
id: set_version # 添加 id,version表示输出变量名
run: echo "version=$(TZ=Asia/Shanghai date +'%Y%m%d_%H%M%S')" >> $GITHUB_OUTPUT # $GITHUB_OUTPUT是GitHub Actions提供的一个特殊文件,用于存储步骤的输出变量。
- name: Docker 登录阿里云镜像仓库
uses: docker/login-action@v2
with:
# secrets: 获取github中存储的数据
username: ${{ secrets.ALIYUN_USERNAME }}
password: ${{ secrets.ALIYUN_PASSWORD }}
registry: 仓库链接
- name: 构建和推送 Docker 镜像
run: |
# steps: 表示当前 job 中的步骤
# set_version: 步骤的 id
# outputs: 输出变量(固定)
# version: 具体的变量名
# 构建并推送镜像到仓库
docker build -t 仓库链接/命名空间/镜像仓库:${{ steps.set_version.outputs.version }} .
docker push 仓库链接/命名空间/镜像仓库:${{ steps.set_version.outputs.version }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 复制配置文件到服务器
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
source: "docker-compose.yml"
target: "/www/wwwroot/webshop/server/"
overwrite: true
- name: 部署服务
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
# export: 导出到shell环境中,让docker-compose读取到
# needs: 表示依赖的其他 job
# build: job 的名称
# outputs: 输出变量(固定)
# version: 具体的变量名
export VERSION=${{ needs.build.outputs.version }}
# 进入服务器项目目录,根据个人需要更改
cd /www/wwwroot/webshop/server/
# 登录阿里云镜像仓库
docker login 仓库链接 \
-u ${{ secrets.ALIYUN_USERNAME }} \
-p ${{ secrets.ALIYUN_PASSWORD }}
# 拉取新镜像并部署
docker-compose pull
docker-compose up -d
# 清理旧镜像,只保留最新的两个版本
docker images "仓库链接/命名空间/镜像仓库:*" --format "{{.ID}} {{.CreatedAt}}" | \
sort -k 2 -r | \
awk 'NR>2 {print $1}' | \
xargs -r docker rmi