1# This workflow uses actions that are not certified by GitHub.
2# They are provided by a third-party and are governed by
3# separate terms of service, privacy policy, and support
4# documentation.
5
6# GitHub recommends pinning actions to a commit SHA.
7# To get a newer version, you will need to update the SHA.
8# You can also reference a tag or branch, but the action may change without warning.
9
10name: Publish Docker image
11
12on:
13 workflow_dispatch: # allows manual triggering
14 schedule:
15 # Rebuild daily rather than on every push because it is expensive
16 - cron: '12 4 * * *'
17
18concurrency:
19 group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
20 cancel-in-progress: true
21
22# Fine-grant permission
23# https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token
24permissions:
25 packages: write
26
27jobs:
28 push_to_registry:
29 name: Push Docker image to Docker Hub
30
31 runs-on: ${{ matrix.config.runs_on }}
32 env:
33 COMMIT_SHA: ${{ github.sha }}
34 strategy:
35 fail-fast: false
36 matrix:
37 config:
38 # Multi-stage build
39 # Note: the arm64 images are failing, which prevents the amd64 images from being built
40 # https://github.com/ggml-org/llama.cpp/issues/11888
41 #- { tag: "cpu", dockerfile: ".devops/cpu.Dockerfile", platforms: "linux/amd64,linux/arm64", full: true, light: true, server: true, free_disk_space: false }
42 - { tag: "cpu", dockerfile: ".devops/cpu.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: false, runs_on: "ubuntu-22.04" }
43 - { tag: "cuda cuda12", dockerfile: ".devops/cuda.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: true, runs_on: "ubuntu-22.04", cuda_version: "12.4.0", ubuntu_version: "22.04" }
44 - { tag: "cuda13", dockerfile: ".devops/cuda-new.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: true, runs_on: "ubuntu-22.04", cuda_version: "13.1.0", ubuntu_version: "24.04" }
45 - { tag: "musa", dockerfile: ".devops/musa.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: true, runs_on: "ubuntu-22.04" }
46 - { tag: "intel", dockerfile: ".devops/intel.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: true, runs_on: "ubuntu-22.04" }
47 - { tag: "vulkan", dockerfile: ".devops/vulkan.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: false, runs_on: "ubuntu-22.04" }
48 - { tag: "s390x", dockerfile: ".devops/s390x.Dockerfile", platforms: "linux/s390x", full: true, light: true, server: true, free_disk_space: false, runs_on: "ubuntu-22.04-s390x" }
49 - { tag: "rocm", dockerfile: ".devops/rocm.Dockerfile", platforms: "linux/amd64", full: true, light: true, server: true, free_disk_space: true, runs_on: "ubuntu-22.04" }
50 steps:
51 - name: Check out the repo
52 uses: actions/checkout@v6
53 with:
54 fetch-depth: 0 # preserve git history, so we can determine the build number
55
56 - name: Set up QEMU
57 if: ${{ matrix.config.tag != 's390x' }}
58 uses: docker/setup-qemu-action@v3
59 with:
60 image: tonistiigi/binfmt:qemu-v7.0.0-28
61
62 - name: Set up Docker Buildx
63 uses: docker/setup-buildx-action@v3
64
65 - name: Log in to Docker Hub
66 uses: docker/login-action@v3
67 with:
68 registry: ghcr.io
69 username: ${{ github.repository_owner }}
70 password: ${{ secrets.GITHUB_TOKEN }}
71
72 - name: Determine source tag name
73 id: srctag
74 uses: ./.github/actions/get-tag-name
75 env:
76 BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
77
78 - name: Determine image tag name
79 id: tag
80 shell: bash
81 run: |
82 REPO_OWNER="${GITHUB_REPOSITORY_OWNER@L}" # to lower case
83 REPO_NAME="${{ github.event.repository.name }}"
84 PREFIX="ghcr.io/${REPO_OWNER}/${REPO_NAME}:"
85
86 # list all tags possible
87 tags="${{ matrix.config.tag }}"
88 for tag in $tags; do
89 if [[ "$tag" == "cpu" ]]; then
90 TYPE=""
91 else
92 TYPE="-$tag"
93 fi
94 CACHETAGS="${PREFIX}buildcache${TYPE}"
95 FULLTAGS="${FULLTAGS:+$FULLTAGS,}${PREFIX}full${TYPE},${PREFIX}full${TYPE}-${{ steps.srctag.outputs.name }}"
96 LIGHTTAGS="${LIGHTTAGS:+$LIGHTTAGS,}${PREFIX}light${TYPE},${PREFIX}light${TYPE}-${{ steps.srctag.outputs.name }}"
97 SERVERTAGS="${SERVERTAGS:+$SERVERTAGS,}${PREFIX}server${TYPE},${PREFIX}server${TYPE}-${{ steps.srctag.outputs.name }}"
98 done
99 echo "cache_output_tags=$CACHETAGS" >> $GITHUB_OUTPUT
100 echo "full_output_tags=$FULLTAGS" >> $GITHUB_OUTPUT
101 echo "light_output_tags=$LIGHTTAGS" >> $GITHUB_OUTPUT
102 echo "server_output_tags=$SERVERTAGS" >> $GITHUB_OUTPUT
103 echo "cache_output_tags=$CACHETAGS" # print out for debugging
104 echo "full_output_tags=$FULLTAGS" # print out for debugging
105 echo "light_output_tags=$LIGHTTAGS" # print out for debugging
106 echo "server_output_tags=$SERVERTAGS" # print out for debugging
107 env:
108 GITHUB_REPOSITORY_OWNER: '${{ github.repository_owner }}'
109
110 - name: Free Disk Space (Ubuntu)
111 if: ${{ matrix.config.free_disk_space == true }}
112 uses: ggml-org/free-disk-space@v1.3.1
113 with:
114 # this might remove tools that are actually needed,
115 # if set to "true" but frees about 6 GB
116 tool-cache: false
117
118 # all of these default to true, but feel free to set to
119 # "false" if necessary for your workflow
120 android: true
121 dotnet: true
122 haskell: true
123 large-packages: true
124 docker-images: true
125 swap-storage: true
126
127 - name: Build and push Full Docker image (tagged + versioned)
128 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.full == true }}
129 uses: docker/build-push-action@v6
130 with:
131 context: .
132 push: true
133 platforms: ${{ matrix.config.platforms }}
134 # tag list is generated from step above
135 tags: ${{ steps.tag.outputs.full_output_tags }}
136 file: ${{ matrix.config.dockerfile }}
137 target: full
138 provenance: false
139 build-args: |
140 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}
141 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}
142 # using github experimental cache
143 #cache-from: type=gha
144 #cache-to: type=gha,mode=max
145 # return to this if the experimental github cache is having issues
146 #cache-to: type=local,dest=/tmp/.buildx-cache
147 #cache-from: type=local,src=/tmp/.buildx-cache
148 # using registry cache (no storage limit)
149 cache-from: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }}
150 cache-to: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }},mode=max
151
152 - name: Build and push Light Docker image (tagged + versioned)
153 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.light == true }}
154 uses: docker/build-push-action@v6
155 with:
156 context: .
157 push: true
158 platforms: ${{ matrix.config.platforms }}
159 # tag list is generated from step above
160 tags: ${{ steps.tag.outputs.light_output_tags }}
161 file: ${{ matrix.config.dockerfile }}
162 target: light
163 provenance: false
164 build-args: |
165 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}
166 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}
167 # using github experimental cache
168 #cache-from: type=gha
169 #cache-to: type=gha,mode=max
170 # return to this if the experimental github cache is having issues
171 #cache-to: type=local,dest=/tmp/.buildx-cache
172 #cache-from: type=local,src=/tmp/.buildx-cache
173 # using registry cache (no storage limit)
174 cache-from: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }}
175 cache-to: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }},mode=max
176
177 - name: Build and push Server Docker image (tagged + versioned)
178 if: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.config.server == true }}
179 uses: docker/build-push-action@v6
180 with:
181 context: .
182 push: true
183 platforms: ${{ matrix.config.platforms }}
184 # tag list is generated from step above
185 tags: ${{ steps.tag.outputs.server_output_tags }}
186 file: ${{ matrix.config.dockerfile }}
187 target: server
188 provenance: false
189 build-args: |
190 ${{ matrix.config.ubuntu_version && format('UBUNTU_VERSION={0}', matrix.config.ubuntu_version) || '' }}
191 ${{ matrix.config.cuda_version && format('CUDA_VERSION={0}', matrix.config.cuda_version) || '' }}
192 # using github experimental cache
193 #cache-from: type=gha
194 #cache-to: type=gha,mode=max
195 # return to this if the experimental github cache is having issues
196 #cache-to: type=local,dest=/tmp/.buildx-cache
197 #cache-from: type=local,src=/tmp/.buildx-cache
198 # using registry cache (no storage limit)
199 cache-from: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }}
200 cache-to: type=registry,ref=${{ steps.tag.outputs.cache_output_tags }},mode=max
201
202 create_tag:
203 name: Create and push git tag
204 runs-on: ubuntu-22.04
205 permissions:
206 contents: write
207
208 steps:
209 - name: Clone
210 id: checkout
211 uses: actions/checkout@v6
212 with:
213 fetch-depth: 0
214
215 - name: Determine source tag name
216 id: srctag
217 uses: ./.github/actions/get-tag-name
218 env:
219 BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
220
221 - name: Create and push git tag
222 env:
223 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
224 run: |
225 git tag ${{ steps.srctag.outputs.name }} || exit 0
226 git push origin ${{ steps.srctag.outputs.name }} || exit 0