11# example of a Docker container for CUDA.jl with a specific toolkit embedded at run time.
2+ #
3+ # supports selecting a Julia and CUDA toolkit version, as well as baking in specific
4+ # versions of the CUDA.jl package (identified by a spec recorgnized by the Pkg REPL).
5+ #
6+ # CUDA.jl and other packages are shipped in a system depot, with the user depot mounted
7+ # at `/depot`. persistency is possible by mounting a volume at this location.
8+ # running with reduced privileges (by using `--user`) is also supported.
29
3- FROM julia:1.8-bullseye
10+ ARG JULIA_VERSION=1
11+ FROM julia:${JULIA_VERSION}
12+
13+ ARG CUDA_VERSION=12.6
14+
15+ ARG PACKAGE_SPEC=CUDA
16+
17+ LABEL org.opencontainers.image.authors="Tim Besard <tim.besard@gmail.com>" \
18+ org.opencontainers.image.description="A CUDA.jl container with CUDA ${CUDA_VERSION} and Julia ${JULIA_VERSION}" \
19+ org.opencontainers.image.title="CUDA.jl" \
20+ org.opencontainers.image.url="https://juliagpu.org/cuda/" \
21+ org.opencontainers.image.source="https://github.com/JuliaGPU/CUDA.jl" \
22+ org.opencontainers.image.licenses="MIT"
423
524
625# system-wide packages
726
27+ # no trailing ':' as to ensure we don't touch anything outside this directory. without it,
28+ # Julia touches the compilecache timestamps in its shipped depot (for some reason; a bug?)
829ENV JULIA_DEPOT_PATH=/usr/local/share/julia
930
10- RUN julia -e 'using Pkg; Pkg.add("CUDA")'
31+ # pre-install the CUDA toolkit from an artifact. we do this separately from CUDA.jl so that
32+ # this layer can be cached independently. it also avoids double precompilation of CUDA.jl in
33+ # order to call `CUDA.set_runtime_version!`.
34+ RUN julia -e '#= configure the preference =# \
35+ env = "/usr/local/share/julia/environments/v$(VERSION.major).$(VERSION.minor)"; \
36+ mkpath(env); \
37+ write("$env/LocalPreferences.toml", \
38+ "[CUDA_Runtime_jll]\n version = \" ' ${CUDA_VERSION}'\" "); \
39+ \
40+ #= install the JLL =# \
41+ using Pkg; \
42+ Pkg.add("CUDA_Runtime_jll")' && \
43+ # = demote the JLL to an [extras] dep =# \
44+ find /usr/local/share/julia/environments -name Project.toml -exec sed -i 's/deps/extras/' {} + && \
45+ # = remove nondeterminisms =# \
46+ cd /usr/local/share/julia && \
47+ rm -rf compiled registries scratchspaces logs && \
48+ find -exec touch -h -d "@0" {} + && \
49+ touch -h -d "@0" /usr/local/share
1150
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()'
51+ # install CUDA.jl itself
52+ RUN julia -e 'using Pkg; pkg"add ' ${PACKAGE_SPEC}'"; \
53+ using CUDA; CUDA.precompile_runtime()' && \
54+ # = remove useless stuff =# \
55+ cd /usr/local/share/julia && \
56+ rm -rf registries scratchspaces logs
1957
2058
2159# user environment
@@ -25,6 +63,17 @@ RUN julia -e 'using CUDA; CUDA.precompile_runtime()'
2563# case there might not be a (writable) home directory.
2664
2765RUN mkdir -m 0777 /depot
28- ENV JULIA_DEPOT_PATH=/depot:/usr/local/share/julia
66+
67+ # we add the user environment from a start-up script
68+ # so that the user can mount `/depot` for persistency
69+ ENV JULIA_DEPOT_PATH=/usr/local/share/julia:
70+ COPY <<EOF /usr/local/share/julia/config/startup.jl
71+ if !isdir("/depot/environments/v$(VERSION.major).$(VERSION.minor)" )
72+ mkpath("/depot/environments" )
73+ cp("/usr/local/share/julia/environments/v$(VERSION.major).$(VERSION.minor)" ,
74+ "/depot/environments/v$(VERSION.major).$(VERSION.minor)" )
75+ end
76+ pushfirst!(DEPOT_PATH, "/depot" )
77+ EOF
2978
3079WORKDIR "/workspace"
0 commit comments