Skip to content

Commit a4a071b

Browse files
committed
Update Dockerfile and add workflow to register.
[ci skip]
1 parent 830c49b commit a4a071b

File tree

3 files changed

+159
-10
lines changed

3 files changed

+159
-10
lines changed

.github/workflows/Container.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: Publish Docker image
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: 'Tag to build instead'
8+
required: false
9+
default: ''
10+
mark_as_latest:
11+
description: 'Mark as latest'
12+
type: boolean
13+
required: false
14+
default: false
15+
push:
16+
tags:
17+
- 'v*'
18+
branches:
19+
- master
20+
21+
jobs:
22+
push_to_registry:
23+
name: Build container - Julia ${{ matrix.julia }} - CUDA ${{ matrix.cuda }}
24+
runs-on: ubuntu-latest
25+
permissions:
26+
contents: read
27+
packages: write
28+
29+
strategy:
30+
matrix:
31+
julia: ["1.10", "1.11"]
32+
cuda: ["11.8", "12.6"]
33+
include:
34+
- julia: "1.11"
35+
cuda: "12.6"
36+
default: true
37+
38+
steps:
39+
- name: Check out the repo
40+
uses: actions/checkout@v4
41+
42+
- name: Check out the package
43+
uses: actions/checkout@v4
44+
with:
45+
ref: ${{ inputs.ref || github.ref_name }}
46+
path: package
47+
48+
- name: Get package spec
49+
id: pkg
50+
run: |
51+
if [[ -n "${{ inputs.tag }}" ]]; then
52+
echo "ref=${{ inputs.tag }}" >> $GITHUB_OUTPUT
53+
echo "name=${{ inputs.tag }}" >> $GITHUB_OUTPUT
54+
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
55+
echo "ref=${{ github.ref_name }}" >> $GITHUB_OUTPUT
56+
echo "name=${{ github.ref_name }}" >> $GITHUB_OUTPUT
57+
else
58+
echo "ref=${{ github.sha }}" >> $GITHUB_OUTPUT
59+
echo "name=dev" >> $GITHUB_OUTPUT
60+
fi
61+
62+
VERSION=$(grep "^version = " package/Project.toml | cut -d'"' -f2)
63+
echo "version=$VERSION" >> $GITHUB_OUTPUT
64+
65+
- name: Log in to registry
66+
uses: docker/login-action@v3
67+
with:
68+
registry: ghcr.io
69+
username: ${{ github.actor }}
70+
password: ${{ secrets.GITHUB_TOKEN }}
71+
72+
- name: Extract metadata
73+
id: meta
74+
uses: docker/metadata-action@v5
75+
with:
76+
images: ghcr.io/${{ github.repository }}
77+
tags: |
78+
type=raw,value=${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ matrix.cuda }}
79+
type=raw,value=latest,enable=${{ matrix.default == true && (github.ref_type == 'tag' || inputs.mark_as_latest) }}
80+
type=raw,value=dev,enable=${{ matrix.default == true && github.ref_type == 'branch' && inputs.tag == '' }}
81+
labels: |
82+
org.opencontainers.image.version=${{ steps.pkg.outputs.version }}
83+
84+
- name: Set up Docker Buildx
85+
uses: docker/setup-buildx-action@v3
86+
87+
- name: Build and push image
88+
uses: docker/build-push-action@v6
89+
with:
90+
context: .
91+
push: true
92+
provenance: false # the build fetches the repo again, so provenance tracking is not useful
93+
tags: ${{ steps.meta.outputs.tags }}
94+
labels: ${{ steps.meta.outputs.labels }}
95+
build-args: |
96+
JULIA_VERSION=${{ matrix.julia }}
97+
CUDA_VERSION=${{ matrix.cuda }}
98+
PACKAGE_SPEC=CUDA#${{ steps.pkg.outputs.ref }}

Dockerfile

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,52 @@
11
# example of a Docker container for CUDA.jl with a specific toolkit embedded at run time.
22

3-
FROM julia:1.8-bullseye
3+
ARG JULIA_VERSION=1
4+
FROM julia:${JULIA_VERSION}
5+
6+
ARG CUDA_VERSION=12.6
7+
8+
ARG PACKAGE_SPEC=CUDA
9+
10+
LABEL org.opencontainers.image.authors="Tim Besard <[email protected]>"
11+
LABEL org.opencontainers.image.description="CUDA.jl container with CUDA ${CUDA_VERSION} installed for Julia ${JULIA_VERSION}"
12+
LABEL org.opencontainers.image.title="CUDA.jl"
13+
LABEL org.opencontainers.image.url="https://juliagpu.org/cuda/"
14+
LABEL org.opencontainers.image.source="https://github.com/JuliaGPU/CUDA.jl"
15+
LABEL org.opencontainers.image.licenses="MIT"
416

517

618
# system-wide packages
719

20+
# no trailing ':' as to ensure we don't touch anything outside this directory. without it,
21+
# Julia touches the compilecache timestamps in its shipped depot (for some reason; a bug?)
822
ENV JULIA_DEPOT_PATH=/usr/local/share/julia
923

10-
RUN julia -e 'using Pkg; Pkg.add("CUDA")'
24+
# pre-install the CUDA toolkit from an artifact. we do this separately from CUDA.jl so that
25+
# this layer can be cached independently. it also avoids double precompilation of CUDA.jl in
26+
# order to call `CUDA.set_runtime_version!`.
27+
RUN julia -e '#= configure the preference =# \
28+
env = "/usr/local/share/julia/environments/v$(VERSION.major).$(VERSION.minor)"; \
29+
mkpath(env); \
30+
write("$env/LocalPreferences.toml", \
31+
"[CUDA_Runtime_jll]\nversion = \"'${CUDA_VERSION}'\""); \
32+
\
33+
#= install the JLL =# \
34+
using Pkg; \
35+
Pkg.add("CUDA_Runtime_jll")' && \
36+
#= demote the JLL to an [extras] dep =# \
37+
find /usr/local/share/julia/environments -name Project.toml -exec sed -i 's/deps/extras/' {} + && \
38+
#= remove nondeterminisms =# \
39+
cd /usr/local/share/julia && \
40+
rm -rf compiled registries scratchspaces logs && \
41+
find -exec touch -h -d "@0" {} + && \
42+
touch -h -d "@0" /usr/local/share
1143

12-
# hard-code a CUDA toolkit version
13-
RUN julia -e 'using CUDA; CUDA.set_runtime_version!(v"12.2")'
14-
# re-importing CUDA.jl below will trigger a download of the relevant artifacts
15-
16-
# generate the device runtime library for all known and supported devices.
17-
# this is to avoid having to do this over and over at run time.
18-
RUN julia -e 'using CUDA; CUDA.precompile_runtime()'
44+
# install CUDA.jl itself
45+
RUN julia -e 'using Pkg; pkg"add '${PACKAGE_SPEC}'"; \
46+
using CUDA; CUDA.precompile_runtime()' && \
47+
#= remove useless stuff =# \
48+
cd /usr/local/share/julia && \
49+
rm -rf registries scratchspaces logs
1950

2051

2152
# user environment
@@ -25,6 +56,17 @@ RUN julia -e 'using CUDA; CUDA.precompile_runtime()'
2556
# case there might not be a (writable) home directory.
2657

2758
RUN mkdir -m 0777 /depot
28-
ENV JULIA_DEPOT_PATH=/depot:/usr/local/share/julia
59+
60+
# we add the user environment from a start-up script
61+
# so that the user can mount `/depot` for persistency
62+
ENV JULIA_DEPOT_PATH=/usr/local/share/julia:
63+
COPY <<EOF /usr/local/share/julia/config/startup.jl
64+
if !isdir("/depot/environments/v$(VERSION.major).$(VERSION.minor)")
65+
mkpath("/depot/environments")
66+
cp("/usr/local/share/julia/environments/v$(VERSION.major).$(VERSION.minor)",
67+
"/depot/environments/v$(VERSION.major).$(VERSION.minor)")
68+
end
69+
pushfirst!(DEPOT_PATH, "/depot")
70+
EOF
2971

3072
WORKDIR "/workspace"

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ This may take a while, as it will precompile the package and download a suitable
5959
the CUDA toolkit. If your GPU is not fully supported, the above command (or any other
6060
command that initializes the toolkit) will issue a warning.
6161

62+
For quick testing, you can also use [the `juliagpu/cuda.jl` container
63+
image](https://github.com/JuliaGPU/CUDA.jl/pkgs/container/cuda.jl/versions) from the GitHub
64+
Container Registry, which provides Julia, a precompiled version of CUDA.jl, and a matching
65+
CUDA toolkit:
66+
67+
```sh
68+
docker run -it --rm --gpus=all ghcr.io/juliagpu/cuda.jl:latest # other tags available too
69+
```
70+
6271
For more usage instructions and other information, please refer to [the
6372
documentation](https://juliagpu.github.io/CUDA.jl/stable/).
6473

0 commit comments

Comments
 (0)