mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-15 13:55: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": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"Bash(tree:*)"
|
"Bash(tree:*)",
|
||||||
|
"Bash(pip show:*)",
|
||||||
|
"Bash(git rev-parse:*)",
|
||||||
|
"Bash(chmod:*)",
|
||||||
|
"Bash(test:*)",
|
||||||
|
"Bash(lsof:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"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:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- dev
|
|
||||||
tags:
|
tags:
|
||||||
- v*
|
- v*
|
||||||
|
|
||||||
|
|
@ -13,429 +12,14 @@ env:
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
|
|
||||||
jobs:
|
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:
|
build-slim-image:
|
||||||
runs-on: ${{ matrix.runner }}
|
name: Build Slim Image (amd64)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- platform: linux/amd64
|
|
||||||
runner: ubuntu-latest
|
|
||||||
- platform: linux/arm64
|
|
||||||
runner: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
steps:
|
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: Set repository and image name to lowercase
|
||||||
run: |
|
run: |
|
||||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||||
|
|
@ -443,28 +27,20 @@ jobs:
|
||||||
env:
|
env:
|
||||||
IMAGE_NAME: '${{ github.repository }}'
|
IMAGE_NAME: '${{ github.repository }}'
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
run: |
|
|
||||||
platform=${{ matrix.platform }}
|
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
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
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Extract metadata for Docker images (slim tag)
|
- name: Extract metadata for Docker images
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
|
|
@ -489,312 +65,37 @@ jobs:
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
${{ github.ref_type == 'tag' && 'type=raw,value=main' || '' }}
|
||||||
flavor: |
|
flavor: |
|
||||||
prefix=cache-slim-${{ matrix.platform }}-
|
prefix=cache-slim-linux-amd64-
|
||||||
latest=false
|
latest=false
|
||||||
|
|
||||||
- name: Build Docker image (slim)
|
- name: Build and push Docker image (slim)
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
id: build
|
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
platforms: ${{ matrix.platform }}
|
platforms: linux/amd64
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
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-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
|
||||||
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
|
||||||
build-args: |
|
build-args: |
|
||||||
BUILD_HASH=${{ github.sha }}
|
BUILD_HASH=${{ github.sha }}
|
||||||
USE_SLIM=true
|
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
|
- name: Inspect image
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }}
|
||||||
|
|
||||||
merge-cuda-images:
|
- name: Output image tags
|
||||||
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: |
|
run: |
|
||||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
echo "## 🐳 Docker 镜像构建成功" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
env:
|
echo "**镜像标签:**" >> $GITHUB_STEP_SUMMARY
|
||||||
IMAGE_NAME: '${{ github.repository }}'
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
|
||||||
- name: Download digests
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
uses: actions/download-artifact@v5
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
with:
|
echo "**拉取命令:**" >> $GITHUB_STEP_SUMMARY
|
||||||
pattern: digests-cuda-*
|
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
||||||
path: /tmp/digests
|
echo "docker pull ${{ env.FULL_IMAGE_NAME }}:slim" >> $GITHUB_STEP_SUMMARY
|
||||||
merge-multiple: true
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
- 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 }}
|
|
||||||
|
|
|
||||||
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
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
MANIFEST
|
MANIFEST
|
||||||
|
data
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# 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
|
ARG BUILD_HASH
|
||||||
|
|
||||||
# Set Node.js options (heap limit Allocation failed - JavaScript heap out of memory)
|
# 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
|
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