mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-13 04:45:19 +00:00
feat: 使用github workflow
This commit is contained in:
parent
88396a16e6
commit
4f6de98909
20 changed files with 3340 additions and 722 deletions
|
|
@ -1,7 +1,12 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(tree:*)"
|
||||
"Bash(tree:*)",
|
||||
"Bash(pip show:*)",
|
||||
"Bash(git rev-parse:*)",
|
||||
"Bash(chmod:*)",
|
||||
"Bash(test:*)",
|
||||
"Bash(lsof:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
|
|
|||
741
.github/workflows/docker-build.yaml
vendored
741
.github/workflows/docker-build.yaml
vendored
|
|
@ -1,11 +1,10 @@
|
|||
name: Create and publish Docker images with specific build args
|
||||
name: Build and Push Docker Image (Production)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
tags:
|
||||
- v*
|
||||
|
||||
|
|
@ -13,429 +12,14 @@ env:
|
|||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
build-main-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (latest)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-main-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-cuda-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (cuda tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-cuda-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (cuda)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_CUDA=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-cuda-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-cuda126-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (cuda126 tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda126,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-cuda126-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (cuda126)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_CUDA=true
|
||||
USE_CUDA_VER=cu126
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-cuda126-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-ollama-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (ollama tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-ollama,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-ollama-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (ollama)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_OLLAMA=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-ollama-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-slim-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
name: Build Slim Image (amd64)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
|
|
@ -443,28 +27,20 @@ jobs:
|
|||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (slim tag)
|
||||
- name: Extract metadata for Docker images
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
|
|
@ -489,312 +65,37 @@ jobs:
|
|||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-slim-${{ matrix.platform }}-
|
||||
prefix=cache-slim-linux-amd64-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (slim)
|
||||
- name: Build and push Docker image (slim)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
platforms: linux/amd64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_SLIM=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-slim-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge-main-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-main-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-main-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-cuda-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-cuda-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
- name: Output image tags
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-cuda-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-cuda126-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-cuda126-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-cuda126-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda126,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-ollama-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-ollama-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-ollama-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default ollama tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-ollama,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-slim-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-slim-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-slim-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default slim tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=slim
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-slim,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
echo "## 🐳 Docker 镜像构建成功" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**镜像标签:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**拉取命令:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ env.FULL_IMAGE_NAME }}:slim" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
|
|
|
|||
800
.github/workflows_bak/docker-build.yaml
vendored
Normal file
800
.github/workflows_bak/docker-build.yaml
vendored
Normal file
|
|
@ -0,0 +1,800 @@
|
|||
name: Create and publish Docker images with specific build args
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
tags:
|
||||
- v*
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
build-main-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (latest)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-main-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-cuda-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (cuda tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-cuda-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (cuda)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_CUDA=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-cuda-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-cuda126-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (cuda126 tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda126,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-cuda126-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (cuda126)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_CUDA=true
|
||||
USE_CUDA_VER=cu126
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-cuda126-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-ollama-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (ollama tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-ollama,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-ollama-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (ollama)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_OLLAMA=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-ollama-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build-slim-image:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (slim tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=slim
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-slim,onlatest=true
|
||||
|
||||
- name: Extract metadata for Docker cache
|
||||
id: cache-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||
flavor: |
|
||||
prefix=cache-slim-${{ matrix.platform }}-
|
||||
latest=false
|
||||
|
||||
- name: Build Docker image (slim)
|
||||
uses: docker/build-push-action@v5
|
||||
id: build
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||
build-args: |
|
||||
BUILD_HASH=${{ github.sha }}
|
||||
USE_SLIM=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-slim-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge-main-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-main-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-main-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-cuda-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-cuda-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-cuda-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-cuda126-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-cuda126-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-cuda126-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default latest tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=cuda126
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-cuda126,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-ollama-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-ollama-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-ollama-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default ollama tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=ollama
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-ollama,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
merge-slim-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-slim-image]
|
||||
steps:
|
||||
# GitHub Packages requires the entire repository name to be in lowercase
|
||||
# although the repository owner has a lowercase username, this prevents some people from running actions after forking
|
||||
- name: Set repository and image name to lowercase
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
env:
|
||||
IMAGE_NAME: '${{ github.repository }}'
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: digests-slim-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker images (default slim tag)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.FULL_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=sha,prefix=git-
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,enable=${{ github.ref == 'refs/heads/main' }},prefix=,suffix=,value=slim
|
||||
flavor: |
|
||||
latest=${{ github.ref == 'refs/heads/main' }}
|
||||
suffix=-slim,onlatest=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.FULL_IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -40,6 +40,7 @@ share/python-wheels/
|
|||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
data
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ FROM --platform=$BUILDPLATFORM node:22-alpine3.20 AS build
|
|||
ARG BUILD_HASH
|
||||
|
||||
# Set Node.js options (heap limit Allocation failed - JavaScript heap out of memory)
|
||||
# ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
|
|
|||
1088
docs/DOCKER-DEPLOYMENT.md
Normal file
1088
docs/DOCKER-DEPLOYMENT.md
Normal file
File diff suppressed because it is too large
Load diff
676
docs/LOCAL-PUSH-GUIDE.md
Normal file
676
docs/LOCAL-PUSH-GUIDE.md
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
# 本地镜像构建与推送指南
|
||||
|
||||
本指南介绍如何在本地构建 Docker 镜像并手动推送到 GitHub Container Registry (GHCR)。
|
||||
|
||||
## 当前仓库信息
|
||||
|
||||
- **仓库**: `ai-friend-coming/open-webui-next`
|
||||
- **镜像仓库**: `ghcr.io/ai-friend-coming/open-webui-next`
|
||||
- **当前分支**: `main`
|
||||
- **当前 commit**: `88396a16e`
|
||||
|
||||
---
|
||||
|
||||
## 前置准备
|
||||
|
||||
### 1. 登录 GitHub Container Registry
|
||||
|
||||
#### 创建 Personal Access Token (PAT)
|
||||
|
||||
1. 访问 https://github.com/settings/tokens
|
||||
2. 点击 "Generate new token" → "Generate new token (classic)"
|
||||
3. 设置权限:
|
||||
- `write:packages` - 推送容器镜像
|
||||
- `read:packages` - 拉取容器镜像
|
||||
- `delete:packages` - (可选) 删除镜像
|
||||
4. 生成并保存 Token
|
||||
|
||||
#### 登录 GHCR
|
||||
|
||||
```bash
|
||||
# 方式 1: 使用 PAT 登录 (推荐)
|
||||
export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
|
||||
|
||||
# 方式 2: 交互式登录
|
||||
docker login ghcr.io -u ai-friend-coming
|
||||
# Password: [输入 PAT]
|
||||
```
|
||||
|
||||
成功登录后会显示:
|
||||
```
|
||||
Login Succeeded
|
||||
```
|
||||
|
||||
### 2. 验证 Docker 环境
|
||||
|
||||
```bash
|
||||
# 检查 Docker 版本
|
||||
docker --version
|
||||
# 推荐: Docker version 24.0.0 或更高
|
||||
|
||||
# 检查 Buildx 插件
|
||||
docker buildx version
|
||||
# 推荐: v0.11.0 或更高
|
||||
|
||||
# 创建 Buildx builder (如果不存在)
|
||||
docker buildx create --name multiarch-builder --use
|
||||
docker buildx inspect --bootstrap
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 构建与推送流程
|
||||
|
||||
### 方式一: 模拟 GitHub Actions 流程 (推荐)
|
||||
|
||||
完全模拟 `.github/workflows/docker-build.yaml` 的构建流程:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# build-and-push.sh
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# ============ 配置变量 ============
|
||||
REGISTRY="ghcr.io"
|
||||
IMAGE_NAME="ai-friend-coming/open-webui-next"
|
||||
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
|
||||
|
||||
# 获取 Git 信息
|
||||
BUILD_HASH=$(git rev-parse HEAD)
|
||||
SHORT_HASH=$(git rev-parse --short HEAD)
|
||||
BRANCH=$(git branch --show-current)
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
|
||||
echo "========================================="
|
||||
echo "构建信息:"
|
||||
echo " 仓库: ${IMAGE_NAME}"
|
||||
echo " 分支: ${BRANCH}"
|
||||
echo " Commit: ${SHORT_HASH}"
|
||||
echo " 时间: ${TIMESTAMP}"
|
||||
echo "========================================="
|
||||
|
||||
# ============ 镜像标签生成 ============
|
||||
TAGS=(
|
||||
"${FULL_IMAGE_NAME}:slim" # 主标签
|
||||
"${FULL_IMAGE_NAME}:${BRANCH}-slim" # 分支标签
|
||||
"${FULL_IMAGE_NAME}:git-${SHORT_HASH}-slim" # Git commit 标签
|
||||
"${FULL_IMAGE_NAME}:${TIMESTAMP}-slim" # 时间戳标签
|
||||
)
|
||||
|
||||
# 如果在 main 分支,添加 latest-slim 标签
|
||||
if [ "$BRANCH" = "main" ]; then
|
||||
TAGS+=("${FULL_IMAGE_NAME}:latest-slim")
|
||||
fi
|
||||
|
||||
# 构建标签参数
|
||||
TAG_ARGS=""
|
||||
for tag in "${TAGS[@]}"; do
|
||||
TAG_ARGS="${TAG_ARGS} -t ${tag}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "将构建以下标签:"
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo " - ${tag}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# ============ 构建镜像 ============
|
||||
echo "开始构建镜像..."
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${BUILD_HASH}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
${TAG_ARGS} \
|
||||
--load \
|
||||
.
|
||||
|
||||
echo ""
|
||||
echo "✅ 镜像构建成功!"
|
||||
echo ""
|
||||
|
||||
# ============ 推送镜像 ============
|
||||
read -p "是否推送镜像到 GHCR? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "开始推送镜像..."
|
||||
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo "推送: ${tag}"
|
||||
docker push "${tag}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✅ 所有镜像推送成功!"
|
||||
echo ""
|
||||
echo "拉取命令:"
|
||||
echo " docker pull ${FULL_IMAGE_NAME}:slim"
|
||||
echo ""
|
||||
echo "查看镜像:"
|
||||
echo " https://github.com/${IMAGE_NAME}/pkgs/container/open-webui-next"
|
||||
else
|
||||
echo "跳过推送"
|
||||
fi
|
||||
|
||||
# ============ 清理 ============
|
||||
echo ""
|
||||
read -p "是否清理本地构建缓存? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "清理构建缓存..."
|
||||
docker builder prune -f
|
||||
echo "✅ 缓存清理完成"
|
||||
fi
|
||||
```
|
||||
|
||||
**使用方法**:
|
||||
|
||||
```bash
|
||||
# 添加执行权限
|
||||
chmod +x build-and-push.sh
|
||||
|
||||
# 执行构建
|
||||
./build-and-push.sh
|
||||
```
|
||||
|
||||
### 方式二: 手动分步执行
|
||||
|
||||
#### 1. 构建镜像
|
||||
|
||||
```bash
|
||||
# 获取当前 commit SHA
|
||||
BUILD_HASH=$(git rev-parse HEAD)
|
||||
SHORT_HASH=$(git rev-parse --short HEAD)
|
||||
|
||||
# 构建镜像
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${BUILD_HASH}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:main-slim \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:git-${SHORT_HASH}-slim \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
**构建参数说明**:
|
||||
- `--platform linux/amd64`: 构建 x86_64 架构镜像
|
||||
- `--build-arg BUILD_HASH`: 传入 Git commit SHA
|
||||
- `--build-arg USE_SLIM=true`: 构建精简版 (不预装模型)
|
||||
- `-t`: 指定镜像标签 (可以多个)
|
||||
- `--load`: 加载到本地 Docker (用于单平台构建)
|
||||
|
||||
#### 2. 验证镜像
|
||||
|
||||
```bash
|
||||
# 查看镜像大小
|
||||
docker images | grep open-webui-next
|
||||
|
||||
# 查看镜像详细信息
|
||||
docker inspect ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
|
||||
# 测试运行
|
||||
docker run --rm -p 8080:8080 ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
```
|
||||
|
||||
#### 3. 推送镜像
|
||||
|
||||
```bash
|
||||
# 推送所有标签
|
||||
docker push ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
docker push ghcr.io/ai-friend-coming/open-webui-next:main-slim
|
||||
docker push ghcr.io/ai-friend-coming/open-webui-next:git-${SHORT_HASH}-slim
|
||||
```
|
||||
|
||||
或批量推送:
|
||||
|
||||
```bash
|
||||
# 批量推送
|
||||
docker images | grep "ghcr.io/ai-friend-coming/open-webui-next" | awk '{print $1":"$2}' | xargs -I {} docker push {}
|
||||
```
|
||||
|
||||
#### 4. 验证推送
|
||||
|
||||
```bash
|
||||
# 从 GHCR 拉取验证
|
||||
docker pull ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
|
||||
# 访问 GitHub Packages 页面
|
||||
# https://github.com/ai-friend-coming/open-webui-next/pkgs/container/open-webui-next
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 构建不同镜像变体
|
||||
|
||||
### Slim 版本 (默认, 推荐)
|
||||
|
||||
```bash
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- 镜像较小 (~7.8GB)
|
||||
- 首次运行时自动下载 AI 模型
|
||||
- 适合生产环境
|
||||
|
||||
### 标准版本 (预装模型)
|
||||
|
||||
```bash
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=false \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:latest \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- 镜像较大 (~10GB)
|
||||
- 预装 AI 模型,启动更快
|
||||
- 适合离线环境
|
||||
|
||||
### CUDA 版本 (GPU 加速)
|
||||
|
||||
```bash
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_CUDA=true \
|
||||
--build-arg USE_CUDA_VER=cu128 \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:cuda \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- 支持 NVIDIA GPU 加速
|
||||
- 需要宿主机安装 NVIDIA Docker runtime
|
||||
- 镜像更大 (~15GB)
|
||||
|
||||
---
|
||||
|
||||
## 高级功能
|
||||
|
||||
### 1. 多架构构建 (amd64 + arm64)
|
||||
|
||||
```bash
|
||||
# 创建 multiarch builder
|
||||
docker buildx create --name multiarch --use
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
# 构建并推送多架构镜像
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
--push \
|
||||
.
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 多架构构建会自动推送 (不支持 `--load`)
|
||||
- ARM64 构建可能需要 1-2 小时
|
||||
|
||||
### 2. 使用缓存加速构建
|
||||
|
||||
```bash
|
||||
# 第一次构建: 导出缓存
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
--cache-to type=registry,ref=ghcr.io/ai-friend-coming/open-webui-next:cache-slim-amd64 \
|
||||
--load \
|
||||
.
|
||||
|
||||
# 后续构建: 使用缓存
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
--cache-from type=registry,ref=ghcr.io/ai-friend-coming/open-webui-next:cache-slim-amd64 \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
**效果**: 构建时间从 5 分钟降低到 1-2 分钟
|
||||
|
||||
### 3. 本地缓存 (更快)
|
||||
|
||||
```bash
|
||||
# 使用本地缓存
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
--cache-to type=local,dest=/tmp/docker-cache \
|
||||
--cache-from type=local,src=/tmp/docker-cache \
|
||||
--load \
|
||||
.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 1. 构建内存不足
|
||||
|
||||
**错误**:
|
||||
```
|
||||
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
- ✅ 确认 Dockerfile 第 30 行已取消注释: `ENV NODE_OPTIONS="--max-old-space-size=4096"`
|
||||
- ✅ 增加 Docker 内存限制: Docker Desktop → Settings → Resources → Memory (建议 8GB+)
|
||||
|
||||
### 2. 推送权限被拒绝
|
||||
|
||||
**错误**:
|
||||
```
|
||||
denied: permission_denied: write_package
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 检查登录状态
|
||||
docker info | grep Username
|
||||
|
||||
# 重新登录
|
||||
docker logout ghcr.io
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
|
||||
|
||||
# 确认 PAT 有 write:packages 权限
|
||||
```
|
||||
|
||||
### 3. 镜像推送超时
|
||||
|
||||
**错误**:
|
||||
```
|
||||
error: timeout exceeded
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 增加 Docker 推送超时
|
||||
export DOCKER_CLIENT_TIMEOUT=300
|
||||
export COMPOSE_HTTP_TIMEOUT=300
|
||||
|
||||
# 或分别推送每个标签
|
||||
docker push ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
```
|
||||
|
||||
### 4. Buildx 不可用
|
||||
|
||||
**错误**:
|
||||
```
|
||||
ERROR: buildx: command not found
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 更新 Docker Desktop 到最新版本
|
||||
# 或手动安装 Buildx 插件
|
||||
mkdir -p ~/.docker/cli-plugins
|
||||
curl -Lo ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.11.2/buildx-v0.11.2.linux-amd64
|
||||
chmod +x ~/.docker/cli-plugins/docker-buildx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 清理与维护
|
||||
|
||||
### 清理本地镜像
|
||||
|
||||
```bash
|
||||
# 删除 dangling 镜像
|
||||
docker image prune -f
|
||||
|
||||
# 删除所有未使用的镜像
|
||||
docker image prune -a -f
|
||||
|
||||
# 删除特定镜像
|
||||
docker rmi ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
```
|
||||
|
||||
### 清理构建缓存
|
||||
|
||||
```bash
|
||||
# 清理 Buildx 缓存
|
||||
docker buildx prune -f
|
||||
|
||||
# 清理所有 Docker 缓存 (谨慎使用)
|
||||
docker system prune -a --volumes -f
|
||||
```
|
||||
|
||||
### 查看镜像层信息
|
||||
|
||||
```bash
|
||||
# 使用 dive 工具分析镜像
|
||||
docker run --rm -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
wagoodman/dive:latest \
|
||||
ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 自动化脚本示例
|
||||
|
||||
### 完整的 CI/CD 本地模拟脚本
|
||||
|
||||
保存为 `scripts/local-build.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/local-build.sh
|
||||
# 完整的本地构建、测试、推送流程
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
echo_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# 配置
|
||||
REGISTRY="ghcr.io"
|
||||
IMAGE_NAME="ai-friend-coming/open-webui-next"
|
||||
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
|
||||
VARIANT="slim"
|
||||
|
||||
# Git 信息
|
||||
BUILD_HASH=$(git rev-parse HEAD)
|
||||
SHORT_HASH=$(git rev-parse --short HEAD)
|
||||
BRANCH=$(git branch --show-current)
|
||||
|
||||
# 检查工作目录
|
||||
if [ ! -f "Dockerfile" ]; then
|
||||
echo_error "请在项目根目录运行此脚本"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查未提交的更改
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo_warn "存在未提交的更改:"
|
||||
git status --short
|
||||
read -p "继续构建? (y/n): " -n 1 -r
|
||||
echo
|
||||
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
|
||||
fi
|
||||
|
||||
echo_info "========================================="
|
||||
echo_info "构建配置:"
|
||||
echo_info " 仓库: ${IMAGE_NAME}"
|
||||
echo_info " 分支: ${BRANCH}"
|
||||
echo_info " Commit: ${SHORT_HASH}"
|
||||
echo_info " 变体: ${VARIANT}"
|
||||
echo_info "========================================="
|
||||
|
||||
# 1. 构建镜像
|
||||
echo_info "步骤 1/5: 构建镜像..."
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${BUILD_HASH}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ${FULL_IMAGE_NAME}:${VARIANT} \
|
||||
-t ${FULL_IMAGE_NAME}:git-${SHORT_HASH}-${VARIANT} \
|
||||
--load \
|
||||
.
|
||||
|
||||
# 2. 验证镜像大小
|
||||
echo_info "步骤 2/5: 验证镜像..."
|
||||
IMAGE_SIZE=$(docker images ${FULL_IMAGE_NAME}:${VARIANT} --format "{{.Size}}")
|
||||
echo_info " 镜像大小: ${IMAGE_SIZE}"
|
||||
|
||||
# 3. 测试镜像
|
||||
echo_info "步骤 3/5: 测试镜像..."
|
||||
CONTAINER_ID=$(docker run -d -p 8081:8080 ${FULL_IMAGE_NAME}:${VARIANT})
|
||||
echo_info " 测试容器 ID: ${CONTAINER_ID}"
|
||||
|
||||
# 等待健康检查
|
||||
echo_info " 等待服务启动 (最多 60 秒)..."
|
||||
for i in {1..60}; do
|
||||
if curl -sf http://localhost:8081/health > /dev/null 2>&1; then
|
||||
echo_info " ✅ 健康检查通过"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
[ $i -eq 60 ] && echo_error "健康检查超时" && docker logs ${CONTAINER_ID} && exit 1
|
||||
done
|
||||
|
||||
# 清理测试容器
|
||||
docker stop ${CONTAINER_ID} > /dev/null
|
||||
docker rm ${CONTAINER_ID} > /dev/null
|
||||
echo_info " 测试容器已清理"
|
||||
|
||||
# 4. 推送镜像
|
||||
echo_info "步骤 4/5: 推送镜像到 GHCR..."
|
||||
read -p "确认推送? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
# 检查登录状态
|
||||
if ! docker info | grep -q "Username: ai-friend-coming"; then
|
||||
echo_error "未登录 GHCR,请先登录:"
|
||||
echo " echo \$CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker push ${FULL_IMAGE_NAME}:${VARIANT}
|
||||
docker push ${FULL_IMAGE_NAME}:git-${SHORT_HASH}-${VARIANT}
|
||||
echo_info " ✅ 推送成功"
|
||||
else
|
||||
echo_warn "跳过推送"
|
||||
fi
|
||||
|
||||
# 5. 清理
|
||||
echo_info "步骤 5/5: 清理..."
|
||||
docker builder prune -f > /dev/null
|
||||
echo_info " 构建缓存已清理"
|
||||
|
||||
echo_info "========================================="
|
||||
echo_info "✅ 构建流程完成!"
|
||||
echo_info ""
|
||||
echo_info "拉取命令:"
|
||||
echo_info " docker pull ${FULL_IMAGE_NAME}:${VARIANT}"
|
||||
echo_info ""
|
||||
echo_info "查看镜像:"
|
||||
echo_info " https://github.com/${IMAGE_NAME}/pkgs/container/open-webui-next"
|
||||
echo_info "========================================="
|
||||
```
|
||||
|
||||
**使用方法**:
|
||||
|
||||
```bash
|
||||
chmod +x scripts/local-build.sh
|
||||
./scripts/local-build.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 构建前检查清单
|
||||
|
||||
- [ ] 代码已提交到 Git
|
||||
- [ ] Docker 有足够内存 (8GB+)
|
||||
- [ ] 已登录 GHCR
|
||||
- [ ] 磁盘空间充足 (20GB+)
|
||||
|
||||
### 2. 标签命名规范
|
||||
|
||||
```bash
|
||||
# 生产环境
|
||||
ghcr.io/ai-friend-coming/open-webui-next:v1.2.3-slim
|
||||
|
||||
# 测试环境
|
||||
ghcr.io/ai-friend-coming/open-webui-next:dev-slim
|
||||
|
||||
# 特性分支
|
||||
ghcr.io/ai-friend-coming/open-webui-next:feature-auth-slim
|
||||
```
|
||||
|
||||
### 3. 安全建议
|
||||
|
||||
- 不要在脚本中硬编码 PAT
|
||||
- 使用环境变量: `export CR_PAT=xxx`
|
||||
- 定期轮换 PAT (90 天)
|
||||
- 使用 `.gitignore` 排除敏感文件
|
||||
|
||||
### 4. 性能优化
|
||||
|
||||
- 使用 `--cache-from` 复用缓存
|
||||
- 本地缓存构建结果到 `/tmp`
|
||||
- 使用 SSD 存储 Docker 数据
|
||||
- 增大 Docker 内存限制
|
||||
|
||||
---
|
||||
|
||||
## 常用命令速查
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
docker buildx build -t IMAGE:TAG --load .
|
||||
|
||||
# 推送
|
||||
docker push IMAGE:TAG
|
||||
|
||||
# 拉取
|
||||
docker pull IMAGE:TAG
|
||||
|
||||
# 登录
|
||||
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
|
||||
|
||||
# 清理
|
||||
docker system prune -a -f
|
||||
|
||||
# 查看镜像
|
||||
docker images | grep open-webui-next
|
||||
|
||||
# 测试镜像
|
||||
docker run --rm -p 8080:8080 IMAGE:TAG
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2024-11-14
|
||||
322
scripts/README.md
Normal file
322
scripts/README.md
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
# 构建脚本使用指南
|
||||
|
||||
本目录包含用于本地构建和推送 Docker 镜像的自动化脚本。
|
||||
|
||||
## 脚本列表
|
||||
|
||||
### 1. `build-and-push.sh` - 完整构建和推送流程 (推荐)
|
||||
|
||||
**功能**: 完整的构建、测试、推送流程,包含健康检查
|
||||
|
||||
**使用方法**:
|
||||
```bash
|
||||
# 1. 登录 GHCR (如需推送)
|
||||
export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
|
||||
|
||||
# 2. 运行脚本
|
||||
./scripts/build-and-push.sh
|
||||
```
|
||||
|
||||
**流程**:
|
||||
1. 检查 Git 状态和未提交更改
|
||||
2. 构建 Docker 镜像 (slim 版本)
|
||||
3. 验证镜像大小和 ID
|
||||
4. 运行健康检查测试 (可选)
|
||||
5. 推送镜像到 GHCR (需确认)
|
||||
6. 清理构建缓存 (可选)
|
||||
|
||||
**适用场景**: 正式发布前的完整测试和推送
|
||||
|
||||
---
|
||||
|
||||
### 2. `quick-build.sh` - 快速本地构建
|
||||
|
||||
**功能**: 快速构建镜像用于本地测试,不推送
|
||||
|
||||
**使用方法**:
|
||||
```bash
|
||||
./scripts/quick-build.sh
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- 无交互式确认
|
||||
- 仅构建,不推送
|
||||
- 构建速度快 (如有缓存)
|
||||
|
||||
**适用场景**: 本地开发和快速测试
|
||||
|
||||
---
|
||||
|
||||
### 3. `simulate-workflow.sh` - 模拟 GitHub Actions
|
||||
|
||||
**功能**: 完整模拟 `.github/workflows/docker-build.yaml` 的执行流程
|
||||
|
||||
**使用方法**:
|
||||
```bash
|
||||
# 设置 CR_PAT (可选)
|
||||
export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN
|
||||
|
||||
# 运行模拟
|
||||
./scripts/simulate-workflow.sh
|
||||
```
|
||||
|
||||
**特点**:
|
||||
- 模拟 GitHub Actions 环境变量
|
||||
- 创建独立的 Buildx builder
|
||||
- 使用 registry 缓存
|
||||
- 输出格式与 GitHub Actions 一致
|
||||
|
||||
**适用场景**:
|
||||
- 测试 workflow 配置
|
||||
- 在推送代码前验证构建流程
|
||||
- 排查 CI/CD 问题
|
||||
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 场景 1: 本地快速测试
|
||||
|
||||
```bash
|
||||
# 1. 快速构建
|
||||
./scripts/quick-build.sh
|
||||
|
||||
# 2. 运行测试
|
||||
docker run -d -p 8080:8080 ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
|
||||
# 3. 验证
|
||||
curl http://localhost:8080/health
|
||||
```
|
||||
|
||||
### 场景 2: 发布新版本
|
||||
|
||||
```bash
|
||||
# 1. 确保代码已提交
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
git push
|
||||
|
||||
# 2. 登录 GHCR
|
||||
export CR_PAT=ghp_xxxxxxxxxxxx
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
|
||||
|
||||
# 3. 构建和推送
|
||||
./scripts/build-and-push.sh
|
||||
# 按提示操作: 运行健康检查 → 确认推送 → 清理缓存
|
||||
|
||||
# 4. 验证推送成功
|
||||
docker pull ghcr.io/ai-friend-coming/open-webui-next:slim
|
||||
```
|
||||
|
||||
### 场景 3: 测试 GitHub Actions workflow
|
||||
|
||||
```bash
|
||||
# 1. 模拟 workflow 执行
|
||||
export CR_PAT=ghp_xxxxxxxxxxxx
|
||||
./scripts/simulate-workflow.sh
|
||||
|
||||
# 2. 查看构建结果
|
||||
docker images | grep open-webui-next
|
||||
|
||||
# 3. 如果成功,推送代码触发真实 workflow
|
||||
git push origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 环境要求
|
||||
|
||||
### 必需软件
|
||||
|
||||
- **Docker**: 24.0.0+
|
||||
- **Docker Buildx**: v0.11.0+
|
||||
- **Git**: 任意版本
|
||||
- **Bash**: 4.0+
|
||||
|
||||
### 系统要求
|
||||
|
||||
- **内存**: 建议 8GB+
|
||||
- **磁盘空间**: 至少 20GB 可用空间
|
||||
- **网络**: 需要访问 ghcr.io
|
||||
|
||||
### Docker 配置
|
||||
|
||||
确保 Docker 有足够的资源:
|
||||
|
||||
```bash
|
||||
# Docker Desktop 配置 (推荐):
|
||||
# - Memory: 8GB
|
||||
# - Swap: 2GB
|
||||
# - Disk image size: 64GB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. 构建失败 - 内存不足
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
- 确认 `Dockerfile` 第 30 行已启用: `ENV NODE_OPTIONS="--max-old-space-size=4096"`
|
||||
- 增加 Docker Desktop 内存限制到 8GB+
|
||||
|
||||
### 2. 推送失败 - 未登录
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
unauthorized: authentication required
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 设置 PAT
|
||||
export CR_PAT=ghp_your_token_here
|
||||
|
||||
# 登录 GHCR
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
|
||||
```
|
||||
|
||||
### 3. 脚本无执行权限
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
Permission denied
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
chmod +x scripts/*.sh
|
||||
```
|
||||
|
||||
### 4. Buildx 不可用
|
||||
|
||||
**错误信息**:
|
||||
```
|
||||
ERROR: buildx: command not found
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 安装 Buildx 插件
|
||||
docker buildx install
|
||||
|
||||
# 或更新 Docker Desktop 到最新版本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 标签规则
|
||||
|
||||
所有脚本都会生成以下标签:
|
||||
|
||||
| 标签格式 | 示例 | 说明 |
|
||||
|---------|------|------|
|
||||
| `slim` | `ghcr.io/ai-friend-coming/open-webui-next:slim` | 主标签 (main 分支) |
|
||||
| `latest-slim` | `ghcr.io/ai-friend-coming/open-webui-next:latest-slim` | 最新版本 (仅 main 分支) |
|
||||
| `{branch}-slim` | `ghcr.io/ai-friend-coming/open-webui-next:main-slim` | 分支标签 |
|
||||
| `git-{sha}-slim` | `ghcr.io/ai-friend-coming/open-webui-next:git-88396a1-slim` | Git commit 标签 |
|
||||
|
||||
---
|
||||
|
||||
## 安全最佳实践
|
||||
|
||||
### PAT (Personal Access Token) 管理
|
||||
|
||||
1. **权限设置**: 仅授予 `read:packages` 和 `write:packages`
|
||||
2. **存储位置**: 使用环境变量,不要硬编码到脚本
|
||||
3. **轮换周期**: 建议每 90 天轮换一次
|
||||
4. **作用域**: 为不同用途创建不同的 PAT
|
||||
|
||||
### 环境变量设置
|
||||
|
||||
```bash
|
||||
# 临时设置 (当前会话)
|
||||
export CR_PAT=ghp_xxxxxxxxxxxx
|
||||
|
||||
# 永久设置 (添加到 ~/.bashrc 或 ~/.zshrc)
|
||||
echo 'export CR_PAT=ghp_xxxxxxxxxxxx' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
**注意**: 不要提交 PAT 到 Git 仓库
|
||||
|
||||
---
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 使用构建缓存
|
||||
|
||||
```bash
|
||||
# 第一次构建会较慢 (5-10 分钟)
|
||||
./scripts/build-and-push.sh
|
||||
|
||||
# 后续构建会使用缓存 (1-2 分钟)
|
||||
# 前提: 没有清理缓存
|
||||
```
|
||||
|
||||
### 并行构建 (高级)
|
||||
|
||||
如果需要同时构建多个变体:
|
||||
|
||||
```bash
|
||||
# 构建 slim 和 cuda 版本
|
||||
docker buildx build --build-arg USE_SLIM=true -t IMAGE:slim . &
|
||||
docker buildx build --build-arg USE_CUDA=true -t IMAGE:cuda . &
|
||||
wait
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 清理命令
|
||||
|
||||
### 清理所有本地镜像
|
||||
|
||||
```bash
|
||||
# 删除所有 open-webui-next 镜像
|
||||
docker images | grep open-webui-next | awk '{print $3}' | xargs docker rmi -f
|
||||
|
||||
# 清理悬空镜像
|
||||
docker image prune -f
|
||||
|
||||
# 清理所有未使用的镜像
|
||||
docker image prune -a -f
|
||||
```
|
||||
|
||||
### 清理构建缓存
|
||||
|
||||
```bash
|
||||
# 清理 Buildx 缓存
|
||||
docker buildx prune -f
|
||||
|
||||
# 清理所有 Docker 数据 (谨慎使用)
|
||||
docker system prune -a --volumes -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [本地推送完整指南](../docs/LOCAL-PUSH-GUIDE.md)
|
||||
- [Docker 部署指南](../docs/DOCKER-DEPLOYMENT.md)
|
||||
- [GitHub Actions Workflow](../.github/workflows/docker-build.yaml)
|
||||
|
||||
---
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如果遇到问题:
|
||||
|
||||
1. 查看脚本输出的错误信息
|
||||
2. 参考本文档的"常见问题"部分
|
||||
3. 查看详细文档: `docs/LOCAL-PUSH-GUIDE.md`
|
||||
4. 提交 Issue: https://github.com/ai-friend-coming/open-webui-next/issues
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2024-11-14
|
||||
215
scripts/build-and-push.sh
Executable file
215
scripts/build-and-push.sh
Executable file
|
|
@ -0,0 +1,215 @@
|
|||
#!/bin/bash
|
||||
# build-and-push.sh - 本地构建并推送镜像到 GHCR
|
||||
# 使用方法: ./scripts/build-and-push.sh
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# ============ 颜色输出 ============
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
echo_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
echo_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
|
||||
|
||||
# ============ 配置变量 ============
|
||||
REGISTRY="ghcr.io"
|
||||
IMAGE_NAME="ai-friend-coming/open-webui-next"
|
||||
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
|
||||
|
||||
# 获取 Git 信息
|
||||
BUILD_HASH=$(git rev-parse HEAD)
|
||||
SHORT_HASH=$(git rev-parse --short HEAD)
|
||||
BRANCH=$(git branch --show-current)
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
|
||||
# 检查工作目录
|
||||
if [ ! -f "Dockerfile" ]; then
|
||||
echo_error "请在项目根目录运行此脚本"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo_info "========================================="
|
||||
echo_info "构建信息:"
|
||||
echo_info " 仓库: ${IMAGE_NAME}"
|
||||
echo_info " 分支: ${BRANCH}"
|
||||
echo_info " Commit: ${SHORT_HASH} (${BUILD_HASH:0:40}...)"
|
||||
echo_info " 时间: ${TIMESTAMP}"
|
||||
echo_info "========================================="
|
||||
echo ""
|
||||
|
||||
# 检查未提交的更改
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo_warn "存在未提交的更改:"
|
||||
git status --short
|
||||
echo ""
|
||||
read -p "继续构建? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo_info "已取消"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============ 镜像标签生成 ============
|
||||
TAGS=(
|
||||
"${FULL_IMAGE_NAME}:slim" # 主标签
|
||||
"${FULL_IMAGE_NAME}:${BRANCH}-slim" # 分支标签
|
||||
"${FULL_IMAGE_NAME}:git-${SHORT_HASH}-slim" # Git commit 标签
|
||||
)
|
||||
|
||||
# 如果在 main 分支,添加 latest-slim 标签
|
||||
if [ "$BRANCH" = "main" ]; then
|
||||
TAGS+=("${FULL_IMAGE_NAME}:latest-slim")
|
||||
fi
|
||||
|
||||
# 构建标签参数
|
||||
TAG_ARGS=""
|
||||
for tag in "${TAGS[@]}"; do
|
||||
TAG_ARGS="${TAG_ARGS} -t ${tag}"
|
||||
done
|
||||
|
||||
echo_info "将构建以下标签:"
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo " - ${tag}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# ============ 构建镜像 ============
|
||||
echo_step "步骤 1/4: 构建 Docker 镜像"
|
||||
echo_info "开始构建镜像 (这可能需要 5-10 分钟)..."
|
||||
echo ""
|
||||
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${BUILD_HASH}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
${TAG_ARGS} \
|
||||
--load \
|
||||
.
|
||||
|
||||
echo ""
|
||||
echo_info "✅ 镜像构建成功!"
|
||||
echo ""
|
||||
|
||||
# ============ 验证镜像 ============
|
||||
echo_step "步骤 2/4: 验证镜像"
|
||||
|
||||
IMAGE_SIZE=$(docker images ${FULL_IMAGE_NAME}:slim --format "{{.Size}}")
|
||||
IMAGE_ID=$(docker images ${FULL_IMAGE_NAME}:slim --format "{{.ID}}")
|
||||
|
||||
echo_info "镜像信息:"
|
||||
echo " - ID: ${IMAGE_ID}"
|
||||
echo " - 大小: ${IMAGE_SIZE}"
|
||||
echo ""
|
||||
|
||||
# ============ 测试镜像 ============
|
||||
echo_step "步骤 3/4: 测试镜像"
|
||||
read -p "是否运行健康检查测试? (y/n): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo_info "启动测试容器 (端口 8081)..."
|
||||
|
||||
CONTAINER_ID=$(docker run -d -p 8081:8080 ${FULL_IMAGE_NAME}:slim)
|
||||
echo_info "容器 ID: ${CONTAINER_ID}"
|
||||
echo ""
|
||||
|
||||
echo_info "等待服务启动 (最多 120 秒)..."
|
||||
HEALTH_CHECK_PASSED=false
|
||||
|
||||
for i in {1..120}; do
|
||||
if curl -sf http://localhost:8081/health > /dev/null 2>&1; then
|
||||
echo_info "✅ 健康检查通过 (耗时 ${i} 秒)"
|
||||
HEALTH_CHECK_PASSED=true
|
||||
break
|
||||
fi
|
||||
|
||||
# 每 10 秒显示一次进度
|
||||
if [ $((i % 10)) -eq 0 ]; then
|
||||
echo_info " 等待中... (${i}/120 秒)"
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ "$HEALTH_CHECK_PASSED" = false ]; then
|
||||
echo_error "健康检查超时!"
|
||||
echo_error "容器日志:"
|
||||
docker logs ${CONTAINER_ID} | tail -50
|
||||
docker stop ${CONTAINER_ID} > /dev/null
|
||||
docker rm ${CONTAINER_ID} > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清理测试容器
|
||||
echo_info "清理测试容器..."
|
||||
docker stop ${CONTAINER_ID} > /dev/null
|
||||
docker rm ${CONTAINER_ID} > /dev/null
|
||||
echo ""
|
||||
else
|
||||
echo_warn "跳过健康检查"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# ============ 推送镜像 ============
|
||||
echo_step "步骤 4/4: 推送镜像到 GHCR"
|
||||
echo_info "将推送 ${#TAGS[@]} 个标签到 ${REGISTRY}"
|
||||
echo ""
|
||||
|
||||
read -p "确认推送? (y/n): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
# 检查登录状态
|
||||
if ! docker info 2>/dev/null | grep -q "Username"; then
|
||||
echo_error "未登录 GHCR!"
|
||||
echo_error "请先执行:"
|
||||
echo " export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN"
|
||||
echo " echo \$CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo_info "开始推送镜像..."
|
||||
echo ""
|
||||
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo_info "推送: ${tag}"
|
||||
docker push "${tag}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo_info "✅ 所有镜像推送成功!"
|
||||
echo ""
|
||||
echo_info "拉取命令:"
|
||||
echo " docker pull ${FULL_IMAGE_NAME}:slim"
|
||||
echo ""
|
||||
echo_info "查看镜像:"
|
||||
echo " https://github.com/${IMAGE_NAME}/pkgs/container/open-webui-next"
|
||||
echo ""
|
||||
else
|
||||
echo_warn "跳过推送"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# ============ 清理 ============
|
||||
echo_info "清理选项:"
|
||||
read -p "是否清理本地构建缓存? (y/n): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo_info "清理构建缓存..."
|
||||
docker builder prune -f
|
||||
echo_info "✅ 缓存清理完成"
|
||||
else
|
||||
echo_warn "保留构建缓存 (下次构建会更快)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo_info "========================================="
|
||||
echo_info "✅ 构建流程完成!"
|
||||
echo_info "========================================="
|
||||
29
scripts/quick-build.sh
Executable file
29
scripts/quick-build.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
# quick-build.sh - 快速本地构建 (不推送)
|
||||
# 使用方法: ./scripts/quick-build.sh
|
||||
|
||||
set -e
|
||||
|
||||
# 获取 Git 信息
|
||||
BUILD_HASH=$(git rev-parse HEAD)
|
||||
SHORT_HASH=$(git rev-parse --short HEAD)
|
||||
|
||||
echo "🏗️ 开始快速构建..."
|
||||
echo "📋 Commit: ${SHORT_HASH}"
|
||||
echo ""
|
||||
|
||||
# 构建镜像
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${BUILD_HASH}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
|
||||
-t ghcr.io/ai-friend-coming/open-webui-next:dev \
|
||||
--load \
|
||||
.
|
||||
|
||||
echo ""
|
||||
echo "✅ 构建完成!"
|
||||
echo ""
|
||||
echo "🚀 运行命令:"
|
||||
echo " docker run -d -p 8080:8080 ghcr.io/ai-friend-coming/open-webui-next:slim"
|
||||
181
scripts/simulate-workflow.sh
Executable file
181
scripts/simulate-workflow.sh
Executable file
|
|
@ -0,0 +1,181 @@
|
|||
#!/bin/bash
|
||||
# simulate-workflow.sh - 模拟 GitHub Actions workflow 完整流程
|
||||
# 使用方法: ./scripts/simulate-workflow.sh
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo_job() { echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; echo -e "${BLUE}[JOB]${NC} $1"; }
|
||||
echo_step() { echo -e "${GREEN}[STEP]${NC} $1"; }
|
||||
echo_info() { echo -e " $1"; }
|
||||
|
||||
# ============ 模拟 GitHub Actions 环境变量 ============
|
||||
export GITHUB_REPOSITORY="ai-friend-coming/open-webui-next"
|
||||
export GITHUB_SHA=$(git rev-parse HEAD)
|
||||
export GITHUB_REF=$(git symbolic-ref HEAD)
|
||||
export GITHUB_REF_NAME=$(git branch --show-current)
|
||||
export IMAGE_NAME="${GITHUB_REPOSITORY,,}" # 转小写
|
||||
export FULL_IMAGE_NAME="ghcr.io/${IMAGE_NAME}"
|
||||
|
||||
echo_job "Build Slim Image (amd64)"
|
||||
echo ""
|
||||
|
||||
# ============ Step 1: Set repository and image name ============
|
||||
echo_step "Set repository and image name to lowercase"
|
||||
echo_info "IMAGE_NAME=${IMAGE_NAME}"
|
||||
echo_info "FULL_IMAGE_NAME=${FULL_IMAGE_NAME}"
|
||||
echo ""
|
||||
|
||||
# ============ Step 2: Checkout repository ============
|
||||
echo_step "Checkout repository"
|
||||
echo_info "Repository: ${GITHUB_REPOSITORY}"
|
||||
echo_info "Branch: ${GITHUB_REF_NAME}"
|
||||
echo_info "Commit: ${GITHUB_SHA:0:7}"
|
||||
echo ""
|
||||
|
||||
# ============ Step 3: Set up Docker Buildx ============
|
||||
echo_step "Set up Docker Buildx"
|
||||
if ! docker buildx inspect github-actions > /dev/null 2>&1; then
|
||||
docker buildx create --name github-actions --use
|
||||
echo_info "Created new builder: github-actions"
|
||||
else
|
||||
docker buildx use github-actions
|
||||
echo_info "Using existing builder: github-actions"
|
||||
fi
|
||||
docker buildx inspect --bootstrap
|
||||
echo ""
|
||||
|
||||
# ============ Step 4: Log in to GitHub Container Registry ============
|
||||
echo_step "Log in to GitHub Container Registry"
|
||||
echo_info "Registry: ghcr.io"
|
||||
echo_info "Username: $(whoami)"
|
||||
|
||||
if [ -z "$CR_PAT" ]; then
|
||||
echo -e "${YELLOW}[WARN]${NC} CR_PAT 环境变量未设置,跳过登录"
|
||||
echo_info "如需推送,请设置: export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN"
|
||||
SKIP_PUSH=true
|
||||
else
|
||||
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin > /dev/null 2>&1
|
||||
echo_info "✅ Login Succeeded"
|
||||
SKIP_PUSH=false
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ============ Step 5: Extract metadata for Docker images ============
|
||||
echo_step "Extract metadata for Docker images"
|
||||
|
||||
# 生成标签
|
||||
if [ "$GITHUB_REF_NAME" = "main" ]; then
|
||||
TAGS=(
|
||||
"${FULL_IMAGE_NAME}:slim"
|
||||
"${FULL_IMAGE_NAME}:latest-slim"
|
||||
"${FULL_IMAGE_NAME}:${GITHUB_REF_NAME}-slim"
|
||||
"${FULL_IMAGE_NAME}:git-${GITHUB_SHA:0:7}-slim"
|
||||
)
|
||||
else
|
||||
TAGS=(
|
||||
"${FULL_IMAGE_NAME}:${GITHUB_REF_NAME}-slim"
|
||||
"${FULL_IMAGE_NAME}:git-${GITHUB_SHA:0:7}-slim"
|
||||
)
|
||||
fi
|
||||
|
||||
echo_info "Tags:"
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo_info " - ${tag}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# 构建标签参数
|
||||
TAG_ARGS=""
|
||||
for tag in "${TAGS[@]}"; do
|
||||
TAG_ARGS="${TAG_ARGS} --tag ${tag}"
|
||||
done
|
||||
|
||||
# ============ Step 6: Extract metadata for Docker cache ============
|
||||
echo_step "Extract metadata for Docker cache"
|
||||
CACHE_TAG="${FULL_IMAGE_NAME}:cache-slim-linux-amd64-${GITHUB_REF_NAME}"
|
||||
echo_info "Cache: ${CACHE_TAG}"
|
||||
echo ""
|
||||
|
||||
# ============ Step 7: Build and push Docker image ============
|
||||
echo_step "Build and push Docker image (slim)"
|
||||
echo_info "Platform: linux/amd64"
|
||||
echo_info "Build args: BUILD_HASH=${GITHUB_SHA}, USE_SLIM=true"
|
||||
echo ""
|
||||
|
||||
if [ "$SKIP_PUSH" = true ]; then
|
||||
# 仅构建,不推送
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${GITHUB_SHA}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
${TAG_ARGS} \
|
||||
--cache-from type=registry,ref=${CACHE_TAG} \
|
||||
--load \
|
||||
.
|
||||
echo ""
|
||||
echo -e "${YELLOW}[WARN]${NC} 跳过推送 (CR_PAT 未设置)"
|
||||
else
|
||||
# 构建并推送
|
||||
read -p "确认推送到 GHCR? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${GITHUB_SHA}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
${TAG_ARGS} \
|
||||
--cache-from type=registry,ref=${CACHE_TAG} \
|
||||
--cache-to type=registry,ref=${CACHE_TAG},mode=max \
|
||||
--push \
|
||||
.
|
||||
echo ""
|
||||
echo_info "✅ Image pushed successfully"
|
||||
else
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_HASH="${GITHUB_SHA}" \
|
||||
--build-arg USE_SLIM=true \
|
||||
${TAG_ARGS} \
|
||||
--cache-from type=registry,ref=${CACHE_TAG} \
|
||||
--load \
|
||||
.
|
||||
echo ""
|
||||
echo -e "${YELLOW}[WARN]${NC} 用户取消推送"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ============ Step 8: Inspect image ============
|
||||
echo_step "Inspect image"
|
||||
if [ "$SKIP_PUSH" = false ] && [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
docker buildx imagetools inspect ${FULL_IMAGE_NAME}:slim
|
||||
else
|
||||
docker images | grep open-webui-next | head -5
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ============ Step 9: Output image tags ============
|
||||
echo_step "Output image tags"
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${GREEN}🐳 Docker 镜像构建成功${NC}"
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
echo "📦 镜像标签:"
|
||||
for tag in "${TAGS[@]}"; do
|
||||
echo " ${tag}"
|
||||
done
|
||||
echo ""
|
||||
echo "🚀 拉取命令:"
|
||||
echo " docker pull ${FULL_IMAGE_NAME}:slim"
|
||||
echo ""
|
||||
echo "🌐 查看镜像:"
|
||||
echo " https://github.com/${GITHUB_REPOSITORY}/pkgs/container/open-webui-next"
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
Loading…
Reference in a new issue