first
This commit is contained in:
@@ -0,0 +1,95 @@
|
|||||||
|
# magic-docker
|
||||||
|
|
||||||
|
一个 action 搞定 Docker 镜像的构建与推送,支持:
|
||||||
|
|
||||||
|
- `context`:指定构建目录(前端/后端在子目录时用)
|
||||||
|
- `dockerfile`:指定 Dockerfile 的完整路径
|
||||||
|
- `preset`:内置方案,对应 action 根目录下的 `vue3.Dockerfile`、`vue3-hash.Dockerfile`、`dotnet.Dockerfile`
|
||||||
|
|
||||||
|
优先级:**`dockerfile` > `preset` > `context` 下的默认 `Dockerfile`**。
|
||||||
|
设置了 `dockerfile` 时完全忽略 `preset`;设置了 `preset` 时用对应的 Dockerfile 构建,构建完自动 push 到 registry。
|
||||||
|
|
||||||
|
## 内置 preset
|
||||||
|
|
||||||
|
| preset | 对应 Dockerfile | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `vue3` | `vue3.Dockerfile` | Vue3 + history 路由,nginx 做 `try_files` 回退并带跨域头 |
|
||||||
|
| `vue3-hash` | `vue3-hash.Dockerfile` | Vue3 + hash 路由,nginx 默认配置 |
|
||||||
|
| `dotnet` | `dotnet.Dockerfile` | .NET self-contained 发布(linux-x64) |
|
||||||
|
|
||||||
|
- 编译全部写在 Dockerfile 里(多阶段构建),action 本身只负责传 `--build-arg VERSION=<tag>`:
|
||||||
|
- vue:`npm ci` → `npm run build-only`(没有该脚本时回退 `npm run build`)→ `npm pkg set version=<tag>`
|
||||||
|
- dotnet:`dotnet publish -r linux-x64 -c Release --self-contained -p:AssemblyName=App -p:Version=<tag>`
|
||||||
|
- `vue3` 的 nginx 配置也内联在 Dockerfile 里:`context` 下有 `nginx.conf` 就用项目的,否则用内置默认配置(history 回退 + 跨域头)。
|
||||||
|
|
||||||
|
## 参数
|
||||||
|
|
||||||
|
| 参数 | 必填 | 默认值 | 说明 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `registry` | 是 | `${{ vars.DOCKER_REGISTRY }}` | Docker registry 地址 |
|
||||||
|
| `user` | 是 | `${{ vars.DOCKER_USER }}` | registry 用户名 |
|
||||||
|
| `pass` | 是 | `${{ vars.DOCKER_PASS }}` | registry 密码 |
|
||||||
|
| `image` | 是 | `${{ github.repository }}` | 镜像名 |
|
||||||
|
| `tag` | 否 | `${{ github.ref_name }}` | 镜像 tag |
|
||||||
|
| `platform` | 否 | `linux/amd64` | 构建平台 |
|
||||||
|
| `context` | 否 | `.` | 构建目录,相对仓库根目录 |
|
||||||
|
| `dockerfile` | 否 | 空 | Dockerfile 完整路径(相对仓库根目录或绝对路径) |
|
||||||
|
| `preset` | 否 | 空 | 内置方案:`vue3` / `vue3-hash` / `dotnet` |
|
||||||
|
| `proxy` | 否 | 空 | 构建时使用的 HTTP(S) 代理 |
|
||||||
|
| `no_proxy` | 否 | 见 action.yml | 不使用代理的地址 |
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
### 使用 preset
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: vue
|
||||||
|
preset: vue3
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: vue
|
||||||
|
preset: vue3-hash
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: backend
|
||||||
|
preset: dotnet
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用自己的 Dockerfile
|
||||||
|
|
||||||
|
指定 `dockerfile` 后 `preset` 会被忽略:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: backend
|
||||||
|
dockerfile: backend/Dockerfile
|
||||||
|
platform: linux/arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
### 只给 context(默认用 context/Dockerfile)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 指定镜像名与 tag
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/magic-docker@main
|
||||||
|
with:
|
||||||
|
context: vue
|
||||||
|
preset: vue3
|
||||||
|
image: simcu/web
|
||||||
|
tag: ${{ github.ref_name }}
|
||||||
|
```
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
# action.yml
|
||||||
|
name: "magic docker build and push"
|
||||||
|
description: "一键构建并推送 Docker 镜像:支持自定义 context / dockerfile,或使用内置 preset(vue3、vue3-hash、dotnet)"
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
registry:
|
||||||
|
description: "Docker registry URL"
|
||||||
|
required: true
|
||||||
|
default: "${{ vars.DOCKER_REGISTRY }}"
|
||||||
|
user:
|
||||||
|
description: "Docker registry username"
|
||||||
|
required: true
|
||||||
|
default: "${{ vars.DOCKER_USER }}"
|
||||||
|
pass:
|
||||||
|
description: "Docker registry password"
|
||||||
|
required: true
|
||||||
|
default: "${{ vars.DOCKER_PASS }}"
|
||||||
|
image:
|
||||||
|
description: "Docker image name"
|
||||||
|
required: true
|
||||||
|
default: "${{ github.repository }}"
|
||||||
|
tag:
|
||||||
|
description: "Docker image tag (default: github.ref_name)"
|
||||||
|
required: false
|
||||||
|
default: "${{ github.ref_name }}"
|
||||||
|
platform:
|
||||||
|
description: "Build platform (default: linux/amd64)"
|
||||||
|
required: false
|
||||||
|
default: "linux/amd64"
|
||||||
|
context:
|
||||||
|
description: "构建目录,相对仓库根目录(默认 .)"
|
||||||
|
required: false
|
||||||
|
default: "."
|
||||||
|
dockerfile:
|
||||||
|
description: "Dockerfile 的完整路径,相对仓库根目录或绝对路径。设置后忽略 preset(默认留空)"
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
preset:
|
||||||
|
description: "内置方案:vue3 / vue3-hash / dotnet。未设置 dockerfile 时生效(默认留空)"
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
# 编译、nginx 配置都在 preset 的 Dockerfile 里(多阶段构建)
|
||||||
|
# 优先级:dockerfile > preset > context 下的默认 Dockerfile
|
||||||
|
- name: build docker image and push
|
||||||
|
uses: docker://docker:git
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: 1
|
||||||
|
REGISTRY: ${{ inputs.registry }}
|
||||||
|
REG_USER: ${{ inputs.user }}
|
||||||
|
REG_PASS: ${{ inputs.pass }}
|
||||||
|
IMAGE: ${{ inputs.image }}
|
||||||
|
TAG: ${{ inputs.tag }}
|
||||||
|
PLATFORM: ${{ inputs.platform }}
|
||||||
|
CONTEXT_DIR: ${{ inputs.context }}
|
||||||
|
DOCKERFILE: ${{ inputs.dockerfile }}
|
||||||
|
PRESET: ${{ inputs.preset }}
|
||||||
|
ACTION_PATH: ${{ github.action_path }}
|
||||||
|
with:
|
||||||
|
entrypoint: "/bin/sh"
|
||||||
|
args: |
|
||||||
|
-c '
|
||||||
|
set -e
|
||||||
|
image="$REGISTRY/$IMAGE:$TAG"
|
||||||
|
dockerfile_path="${DOCKERFILE:-}"
|
||||||
|
preset="${PRESET:-}"
|
||||||
|
build_args=""
|
||||||
|
|
||||||
|
if [ -n "$dockerfile_path" ]; then
|
||||||
|
if [ -n "$preset" ]; then
|
||||||
|
echo "已指定 dockerfile($dockerfile_path),忽略 preset($preset)"
|
||||||
|
fi
|
||||||
|
elif [ -n "$preset" ]; then
|
||||||
|
dockerfile_path="$ACTION_PATH/$preset.Dockerfile"
|
||||||
|
if [ ! -f "$dockerfile_path" ]; then
|
||||||
|
echo "未知 preset:$preset(可选:vue3 / vue3-hash / dotnet)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# preset 的 Dockerfile 用 VERSION 覆盖 package.json 版本 / dotnet Version
|
||||||
|
build_args="VERSION=$TAG"
|
||||||
|
echo "使用 preset:$preset"
|
||||||
|
else
|
||||||
|
dockerfile_path="$CONTEXT_DIR/Dockerfile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "构建目录:$CONTEXT_DIR"
|
||||||
|
echo "Dockerfile:$dockerfile_path"
|
||||||
|
echo "镜像:$image"
|
||||||
|
|
||||||
|
set -- --platform "$PLATFORM" -t "$image" -f "$dockerfile_path"
|
||||||
|
if [ -n "$build_args" ]; then
|
||||||
|
set -- --build-arg "$build_args" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker ps && docker info && \
|
||||||
|
docker build "$@" "$CONTEXT_DIR" && \
|
||||||
|
echo "$image 已经构建完了" && \
|
||||||
|
docker login "$REGISTRY" -u "$REG_USER" -p "$REG_PASS" && \
|
||||||
|
docker push "$image" && \
|
||||||
|
echo "$image 推送成功"
|
||||||
|
'
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# 多阶段构建:先在 SDK 里 self-contained 发布,最终镜像只保留 runtime + 发布产物
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
|
||||||
|
# 由 magic-docker 传入:--build-arg VERSION=<tag>
|
||||||
|
ARG VERSION=0.0.0
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# 构建上下文就是 context 目录
|
||||||
|
COPY . .
|
||||||
|
RUN dotnet publish -r linux-x64 -c Release --self-contained -o /out \
|
||||||
|
-p:AssemblyName=App -p:Version="$VERSION"
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/runtime:10.0
|
||||||
|
ENV TZ Asia/Shanghai
|
||||||
|
COPY --from=build /out /home
|
||||||
|
WORKDIR /home
|
||||||
|
ENTRYPOINT ["./App"]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# 多阶段构建:hash 路由不需要 nginx 回退,最终镜像只保留 nginx + dist
|
||||||
|
FROM node:24 AS build
|
||||||
|
|
||||||
|
# 由 magic-docker 传入:--build-arg VERSION=<tag>
|
||||||
|
ARG VERSION=0.0.0
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 构建上下文就是 context 目录
|
||||||
|
COPY . .
|
||||||
|
RUN npm ci
|
||||||
|
RUN npm pkg set version="$VERSION"
|
||||||
|
|
||||||
|
# 有 build-only 脚本就用它(兼容老项目),否则用 build
|
||||||
|
RUN if npm run 2>/dev/null | grep -q "build-only"; then \
|
||||||
|
npm run build-only; \
|
||||||
|
else \
|
||||||
|
npm run build; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# 多阶段构建:先在 node 里编译,最终镜像只保留 nginx + dist
|
||||||
|
FROM node:24 AS build
|
||||||
|
|
||||||
|
# 由 magic-docker 传入:--build-arg VERSION=<tag>
|
||||||
|
ARG VERSION=0.0.0
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 构建上下文就是 context 目录
|
||||||
|
COPY . .
|
||||||
|
RUN npm ci
|
||||||
|
RUN npm pkg set version="$VERSION"
|
||||||
|
|
||||||
|
# 有 build-only 脚本就用它(兼容老项目),否则用 build
|
||||||
|
RUN if npm run 2>/dev/null | grep -q "build-only"; then \
|
||||||
|
npm run build-only; \
|
||||||
|
else \
|
||||||
|
npm run build; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# history 路由回退 + 跨域:context 里有 nginx.conf 就用项目的,否则用内置默认配置
|
||||||
|
RUN set -e; \
|
||||||
|
if [ -f nginx.conf ]; then \
|
||||||
|
cp nginx.conf /app/nginx.conf; \
|
||||||
|
echo "使用项目自带的 nginx.conf"; \
|
||||||
|
else \
|
||||||
|
printf '%s\n' \
|
||||||
|
'server {' \
|
||||||
|
' listen 80;' \
|
||||||
|
' root /usr/share/nginx/html;' \
|
||||||
|
' index index.html;' \
|
||||||
|
'' \
|
||||||
|
' add_header Access-Control-Allow-Origin * always;' \
|
||||||
|
' add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always;' \
|
||||||
|
' add_header Access-Control-Allow-Headers "*, Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Token" always;' \
|
||||||
|
' add_header Access-Control-Allow-Credentials "true" always;' \
|
||||||
|
'' \
|
||||||
|
' if ($request_method = "OPTIONS") {' \
|
||||||
|
' return 204;' \
|
||||||
|
' }' \
|
||||||
|
'' \
|
||||||
|
' location / {' \
|
||||||
|
' try_files $uri $uri/ /index.html;' \
|
||||||
|
' }' \
|
||||||
|
'}' \
|
||||||
|
> /app/nginx.conf; \
|
||||||
|
echo "使用内置的 nginx.conf"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
COPY --from=build /app/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
Reference in New Issue
Block a user