## 修复问题 - K3s pod 内无法访问 localhost:5000 - 改用宿主机 IP: 173.212.254.252:5000 ## 配置更改 - 更新 .env.local-registry 使用宿主机 IP - 更新 workflow Registry 登录地址 - 更新 K8s deployment 镜像地址 - 配置 Docker daemon 允许不安全的 Registry - 配置 K3s registries.yaml 支持 HTTP Registry ## 测试 - ✅ Runner pod 可以访问 173.212.254.252:5000 - ✅ Docker 登录成功 - ✅ K3s 配置完成 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
318 lines
11 KiB
YAML
318 lines
11 KiB
YAML
name: Build and Push Docker Images
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- develop
|
|
tags:
|
|
- 'v*'
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- develop
|
|
workflow_dispatch:
|
|
inputs:
|
|
component:
|
|
description: 'Component to build (all/ljwx-boot/ljwx-admin/ljwx-bigscreen/ljwx-mysql/ljwx-redis)'
|
|
required: false
|
|
default: 'all'
|
|
version:
|
|
description: 'Version tag (default: use VERSION from .env or branch name)'
|
|
required: false
|
|
|
|
env:
|
|
DOCKER_BUILDKIT: 1
|
|
COMPOSE_DOCKER_CLI_BUILD: 1
|
|
|
|
jobs:
|
|
prepare:
|
|
name: Prepare Build Information
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
version: ${{ steps.version.outputs.version }}
|
|
registry: ${{ steps.config.outputs.registry }}
|
|
components: ${{ steps.components.outputs.matrix }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Load .env configuration
|
|
id: config
|
|
run: |
|
|
# 优先使用本地 Registry 配置
|
|
if [ -f .env.local-registry ]; then
|
|
source .env.local-registry
|
|
echo "registry=${REGISTRY}" >> $GITHUB_OUTPUT
|
|
echo "harbor_host=${HARBOR_HOST}" >> $GITHUB_OUTPUT
|
|
echo "harbor_project=${HARBOR_PROJECT}" >> $GITHUB_OUTPUT
|
|
elif [ -f .env ]; then
|
|
source .env
|
|
echo "registry=${REGISTRY:-173.212.254.252:5000}" >> $GITHUB_OUTPUT
|
|
echo "harbor_host=${HARBOR_HOST:-173.212.254.252:5000}" >> $GITHUB_OUTPUT
|
|
echo "harbor_project=${HARBOR_PROJECT:-ljwx-health}" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "registry=173.212.254.252:5000" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Determine version
|
|
id: version
|
|
run: |
|
|
if [ -n "${{ github.event.inputs.version }}" ]; then
|
|
VERSION="${{ github.event.inputs.version }}"
|
|
elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
|
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
elif [ -f .env ]; then
|
|
source .env
|
|
VERSION="${LJWX_VERSION}"
|
|
else
|
|
VERSION="latest"
|
|
fi
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "Build version: ${VERSION}"
|
|
|
|
- name: Determine components to build
|
|
id: components
|
|
run: |
|
|
COMPONENT="${{ github.event.inputs.component }}"
|
|
if [ -z "$COMPONENT" ] || [ "$COMPONENT" = "all" ]; then
|
|
COMPONENTS='["ljwx-boot", "ljwx-admin", "ljwx-bigscreen", "ljwx-mysql", "ljwx-redis"]'
|
|
else
|
|
COMPONENTS='["'$COMPONENT'"]'
|
|
fi
|
|
echo "matrix=${COMPONENTS}" >> $GITHUB_OUTPUT
|
|
echo "Components to build: ${COMPONENTS}"
|
|
|
|
build-and-push:
|
|
name: Build and Push ${{ matrix.component }}
|
|
needs: prepare
|
|
runs-on: self-hosted
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
component: ${{ fromJson(needs.prepare.outputs.components) }}
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
with:
|
|
platforms: linux/amd64,linux/arm64
|
|
|
|
- name: Log in to Local Registry
|
|
run: |
|
|
echo "admin123" | docker login 173.212.254.252:5000 -u admin --password-stdin
|
|
|
|
- name: Prepare build context
|
|
id: context
|
|
run: |
|
|
COMPONENT="${{ matrix.component }}"
|
|
VERSION="${{ needs.prepare.outputs.version }}"
|
|
REGISTRY="${{ needs.prepare.outputs.registry }}"
|
|
|
|
case "$COMPONENT" in
|
|
ljwx-mysql)
|
|
DOCKERFILE="docker/mysql/Dockerfile"
|
|
CONTEXT="."
|
|
;;
|
|
ljwx-redis)
|
|
DOCKERFILE="docker/redis/Dockerfile"
|
|
CONTEXT="."
|
|
;;
|
|
ljwx-boot)
|
|
DOCKERFILE="ljwx-boot/ljwx-boot-admin/Dockerfile.prod"
|
|
CONTEXT="."
|
|
;;
|
|
ljwx-bigscreen)
|
|
DOCKERFILE="ljwx-bigscreen/bigscreen/Dockerfile.prod"
|
|
CONTEXT="ljwx-bigscreen/bigscreen"
|
|
;;
|
|
ljwx-admin)
|
|
DOCKERFILE="ljwx-admin/Dockerfile"
|
|
CONTEXT="ljwx-admin"
|
|
;;
|
|
*)
|
|
echo "Unknown component: $COMPONENT"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "dockerfile=${DOCKERFILE}" >> $GITHUB_OUTPUT
|
|
echo "context=${CONTEXT}" >> $GITHUB_OUTPUT
|
|
echo "image_name=${REGISTRY}/${COMPONENT}" >> $GITHUB_OUTPUT
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Extract metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ steps.context.outputs.image_name }}
|
|
tags: |
|
|
type=raw,value=${{ steps.context.outputs.version }}
|
|
type=raw,value=latest
|
|
type=sha,prefix={{branch}}-
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: ${{ steps.context.outputs.context }}
|
|
file: ${{ steps.context.outputs.dockerfile }}
|
|
platforms: linux/amd64,linux/arm64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
|
GIT_COMMIT=${{ github.sha }}
|
|
VERSION=${{ steps.context.outputs.version }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
- name: Image digest
|
|
run: echo "Image pushed successfully"
|
|
|
|
deploy-to-k3s:
|
|
name: Deploy to K3s
|
|
needs: [prepare, build-and-push]
|
|
runs-on: self-hosted
|
|
if: success() && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up kubectl context
|
|
run: |
|
|
# Verify kubectl is available
|
|
kubectl version --client
|
|
|
|
# Verify cluster connection
|
|
kubectl cluster-info
|
|
|
|
- name: Create namespace if not exists
|
|
run: |
|
|
kubectl create namespace ljwx-health --dry-run=client -o yaml | kubectl apply -f -
|
|
|
|
- name: Create Local Registry image pull secret
|
|
run: |
|
|
kubectl create secret docker-registry harbor-secret \
|
|
--docker-server=173.212.254.252:5000 \
|
|
--docker-username=admin \
|
|
--docker-password=admin123 \
|
|
--namespace=ljwx-health \
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
|
|
|
- name: Update image tags in deployments
|
|
env:
|
|
VERSION: ${{ needs.prepare.outputs.version }}
|
|
REGISTRY: ${{ needs.prepare.outputs.registry }}
|
|
run: |
|
|
# Update ljwx-boot deployment image tag
|
|
if [ -f ljwx-boot/k8s/deployment.yml ]; then
|
|
sed -i "s|image:.*ljwx-boot:.*|image: ${REGISTRY}/ljwx-boot:${VERSION}|g" ljwx-boot/k8s/deployment.yml
|
|
fi
|
|
|
|
# Update ljwx-bigscreen deployment image tag
|
|
if [ -f ljwx-bigscreen/k8s/prod/deployment.yaml ]; then
|
|
# Fix namespace to ljwx-health
|
|
sed -i 's|namespace: ljwx-system|namespace: ljwx-health|g' ljwx-bigscreen/k8s/prod/deployment.yaml
|
|
# Update image reference
|
|
sed -i "s|\${REGISTRY}/\${IMAGE_NAME}:\${IMAGE_TAG}|${REGISTRY}/ljwx-bigscreen:${VERSION}|g" ljwx-bigscreen/k8s/prod/deployment.yaml
|
|
fi
|
|
|
|
- name: Deploy ljwx-boot
|
|
env:
|
|
DB_USERNAME: ${{ secrets.MYSQL_USERNAME || 'root' }}
|
|
DB_PASSWORD: ${{ secrets.MYSQL_PASSWORD || '123456' }}
|
|
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD || '123456' }}
|
|
JWT_SECRET: ${{ secrets.JWT_SECRET || 'ljwx-default-jwt-secret-change-me' }}
|
|
run: |
|
|
# Apply ConfigMap first
|
|
kubectl apply -f ljwx-boot/k8s/configmap.yml -n ljwx-health || true
|
|
|
|
# Create secret from template
|
|
if [ -f ljwx-boot/k8s/secret.yml.template ]; then
|
|
sed "s|<BASE64_ENCODED_DB_USERNAME>|$(echo -n "${DB_USERNAME}" | base64)|g" ljwx-boot/k8s/secret.yml.template | \
|
|
sed "s|<BASE64_ENCODED_DB_PASSWORD>|$(echo -n "${DB_PASSWORD}" | base64)|g" | \
|
|
sed "s|<BASE64_ENCODED_REDIS_PASSWORD>|$(echo -n "${REDIS_PASSWORD}" | base64)|g" | \
|
|
sed "s|<BASE64_ENCODED_JWT_SECRET>|$(echo -n "${JWT_SECRET}" | base64)|g" | \
|
|
kubectl apply -f - -n ljwx-health
|
|
fi
|
|
|
|
# Apply Service
|
|
kubectl apply -f ljwx-boot/k8s/service.yml -n ljwx-health || true
|
|
|
|
# Apply Deployment
|
|
kubectl apply -f ljwx-boot/k8s/deployment.yml -n ljwx-health
|
|
|
|
# Wait for rollout
|
|
kubectl rollout status deployment/ljwx-boot -n ljwx-health --timeout=5m
|
|
|
|
- name: Deploy ljwx-bigscreen
|
|
run: |
|
|
# Apply ConfigMap
|
|
kubectl apply -f ljwx-bigscreen/k8s/base/configmap.yaml -n ljwx-health || true
|
|
|
|
# Apply Service
|
|
kubectl apply -f ljwx-bigscreen/k8s/prod/service.yaml -n ljwx-health || true
|
|
|
|
# Apply Deployment
|
|
kubectl apply -f ljwx-bigscreen/k8s/prod/deployment.yaml -n ljwx-health
|
|
|
|
# Wait for rollout
|
|
kubectl rollout status deployment/ljwx-bigscreen -n ljwx-health --timeout=5m
|
|
|
|
- name: Verify deployment
|
|
run: |
|
|
echo "## Deployment Status" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# Get pod status
|
|
kubectl get pods -n ljwx-health -o wide >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# Get service status
|
|
echo "### Services" >> $GITHUB_STEP_SUMMARY
|
|
kubectl get svc -n ljwx-health >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# Check deployment health
|
|
BOOT_READY=$(kubectl get deployment ljwx-boot -n ljwx-health -o jsonpath='{.status.readyReplicas}')
|
|
BOOT_DESIRED=$(kubectl get deployment ljwx-boot -n ljwx-health -o jsonpath='{.status.replicas}')
|
|
|
|
if [ "$BOOT_READY" == "$BOOT_DESIRED" ]; then
|
|
echo "✅ ljwx-boot: $BOOT_READY/$BOOT_DESIRED replicas ready" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "⚠️ ljwx-boot: $BOOT_READY/$BOOT_DESIRED replicas ready" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
summary:
|
|
name: Build Summary
|
|
needs: [prepare, build-and-push, deploy-to-k3s]
|
|
runs-on: ubuntu-latest
|
|
if: always()
|
|
steps:
|
|
- name: Check build status
|
|
run: |
|
|
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Version:** ${{ needs.prepare.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Registry:** ${{ needs.prepare.outputs.registry }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Components:** ${{ needs.prepare.outputs.components }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [ "${{ needs.build-and-push.result }}" == "success" ]; then
|
|
echo "✅ All images built and pushed successfully!" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "❌ Some builds failed. Check the logs above." >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
if [ "${{ needs.deploy-to-k3s.result }}" == "success" ]; then
|
|
echo "✅ Deployment to K3s successful!" >> $GITHUB_STEP_SUMMARY
|
|
elif [ "${{ needs.deploy-to-k3s.result }}" == "skipped" ]; then
|
|
echo "⏭️ Deployment skipped (not main/develop branch)" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "❌ Deployment to K3s failed. Check the logs above." >> $GITHUB_STEP_SUMMARY
|
|
fi
|