All,
I'm using Julia in a Docker container designed for development. Various developers use the same Dockerfile on a variety of host machines w/ different architectures. Julia is installed in the Docker image but the git repos holding the source are mounted volumes at run-time. It's working just fine except that every time the container is launched we have the hit for reinstantiating the Julia environment. So, I'm trying to bake the instantiated environment into the Docker image at build time.
After installing Julia into the Docker image I then temporarily COPY the project repos to a directory within the the image that is identical to where they will be mounted during run-time. Here is a snippet of the Dockerfile,
# syntax = edrevo/dockerfile-plus
ARG PROGRAM_NAME=wrong_program
ARG DOCKER_UBUNTU_VERSION=wrong_version
FROM ubuntu:${DOCKER_UBUNTU_VERSION}
SHELL ["/bin/bash", "-c"]
RUN apt-get update \
&& apt-get install -y -qq --no-install-recommends \
libglvnd0 \
libgl1 \
libglx0 \
libegl1 \
libxext6 \
libx11-6 \
glmark2 \
mesa-utils \
&& rm -rf /var/lib/apt/lists/*
# Env vars for the nvidia-container-runtime.
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES graphics,utility,compute
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -qqy --no-install-recommends \
sudo \
apt-utils \
autotools-dev \
build-essential \
ca-certificates \
g++ \
git \
iputils-ping \
libssl-dev \
nano \
openssl \
python-dev \
unzip \
vim \
sed \
x11-apps
RUN update-ca-certificates
# Change to non-root privilege
# https://dev.to/emmanuelnk/using-sudo-without-password-prompt-as-non-root-docker-user-52bg
ARG USERNAME=wrongUser
ARG USERID=1000
ARG GID=101
ARG GROUPNAME=dev
RUN addgroup --gid ${GID} ${GROUPNAME} \
&& adduser --uid ${USERID} --disabled-password --home /home/${USERNAME} --shell /bin/bash --gecos '' ${USERNAME} \
&& adduser ${USERNAME} sudo \
&& adduser ${USERNAME} dev \
&& grep -qxF '%sudo ALL=(ALL) NOPASSWD:ALL' /etc/sudoers || echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${USERNAME}
RUN grep -qxF 'export LS_COLORS="$LS_COLORS:ow=1;34:tw=1;34:"' ~/.bashrc || echo 'export LS_COLORS="$LS_COLORS:ow=1;34:tw=1;34:"' >> ~/.bashrc
ARG TEMPDIR=${THIRDPARTYDIR}/temp
RUN echo "THIRDPARTYDIR = ${THIRDPARTYDIR}" && \
echo "TEMPDIR = ${TEMPDIR}"
#--------------------------------------
# Install julia
#--------------------------------------
ARG JULIA_VERSION
ARG JULIA_DOWNLOAD_FILE
RUN echo "JULIA_VERSION = ${JULIA_VERSION}" && \
echo "JULIA_DOWNLOAD_FILE = ${JULIA_DOWNLOAD_FILE}"
COPY --chown=${USERNAME}:${USERNAME} downloads/${JULIA_DOWNLOAD_FILE} ${THIRDPARTYDIR}/
RUN chown ${USERNAME}:${USERNAME} ${THIRDPARTYDIR}/${JULIA_DOWNLOAD_FILE} && \
chmod 744 ${THIRDPARTYDIR}/${JULIA_DOWNLOAD_FILE}
WORKDIR ${THIRDPARTYDIR}
RUN tar xf ${JULIA_DOWNLOAD_FILE} && \
rm -rf ${JULIA_DOWNLOAD_FILE}
WORKDIR ${THIRDPARTYDIR}
RUN sudo ln -s ${THIRDPARTYDIR}/julia-${JULIA_VERSION}/bin/julia /usr/bin/julia && \
sudo apt-get install -y wget
ENV CMAKE_PREFIX_PATH=${THIRDPARTYDIR}/julia-${JULIA_VERSION}:${CMAKE_PREFIX_PATH}
# instantiate all Julia Packages
RUN echo "intiantiating Julia Packages"
ARG WORKSPACEDIR
RUN mkdir -p ${WORKSPACEDIR}/src/
COPY --chown=${USERNAME}:${USERNAME} JuliaProjectManifests/ ${WORKSPACEDIR}/src/
RUN echo "WORKSPACEDIR = ${WORKSPACEDIR}"
#RUN sudo chown -R ${USERNAME}:${GROUPNAME} /tmp
WORKDIR ${WORKSPACEDIR}/src/
COPY --chown=${USERNAME}:${USERNAME} ./julia_instantiate.sh ${WORKSPACEDIR}/src/
RUN chmod +x ./julia_instantiate.sh
RUN source ./julia_instantiate.sh
#RUN sudo -E -s \
# && source ./julia_instantiate.sh \
# && exit
WORKDIR ${THIRDPARTYDIR}
RUN rm -rf temp
RUN sudo ldconfig
WORKDIR ${THIRDPARTYDIR}/..
CMD ["bash"]
To help clarify more... the ARG environment variables are defined on the command line when kicking off the build. That script looks like:
DOCKER_BUILDKIT=1 docker build \
--no-cache=false \
--network=host \
--rm \
--build-arg PROGRAM_NAME=${PROGRAM_NAME} \
--build-arg WORKSPACEDIR=${WORKSPACEDIR} \
--build-arg USERNAME=${USER} \
--build-arg USERID=${UID} \
--build-arg THIRDPARTYDIR=${THIRDPARTYDIR} \
--build-arg DOCKER_UBUNTU_VERSION=${DOCKER_UBUNTU_VERSION} \
--build-arg JULIA_VERSION=${JULIA_VERSION} \
--build-arg JULIA_DOWNLOAD_FILE=${JULIA_DOWNLOAD_FILE} \
-f ${CDDS}/${DOCKER_BUILD_FOLDER}/${DOCKER_FILE_NAME} \
-t ${DOCKER_IMAGE} \
${DOCKER_BUILD_CONTEXT} \
2>&1 | tee ${CDDS}/${DOCKER_BUILD_FOLDER}/${DOCKER_BUILD_LOG}
When I try to instantiate the project during the docker build I get the following error,
#115 sha256:0c589043bbee81f6e25ae6da0177acfea129c478ba518ca117a39838dc68d6f1
#115 0.148 iKinQP/
#115 0.924 Installing known registries into `~/.julia`
#115 1.032 ERROR: SystemError: mktemp: No such file or directory
#115 1.703 Stacktrace:
#115 1.935 [1] systemerror(::Symbol, ::Int32; extrainfo::Nothing) at ./error.jl:168
#115 2.272 [2] #systemerror#48 at ./error.jl:167 [inlined]
#115 2.279 [3] systemerror at ./error.jl:167 [inlined]
#115 2.279 [4] #mktemp#18 at ./file.jl:589 [inlined]
#115 2.279 [5] mktemp at ./file.jl:587 [inlined] (repeats 2 times)
#115 2.298 [6] probe_platform_engines!(; verbose::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/PlatformEngines.jl:280
#115 2.299 [7] probe_platform_engines! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/PlatformEngines.jl:181 [inlined]
#115 2.299 [8] pkg_server_registry_urls() at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:944
#115 2.349 [9] clone_default_registries(::Pkg.Types.Context; only_if_empty::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:868
#115 2.350 [10] clone_default_registries at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:862 [inlined]
#115 2.350 [11] find_registered!(::Pkg.Types.Context, ::Array{String,1}, ::Array{Base.UUID,1}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1239
#115 2.355 [12] find_registered! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1200 [inlined]
#115 2.355 [13] check_registered(::Pkg.Types.Context, ::Array{Pkg.Types.PackageSpec,1}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Operations.jl:1054
#115 2.356 [14] instantiate(::Pkg.Types.Context; manifest::Nothing, update_registry::Bool, verbose::Bool, platform::Pkg.BinaryPlatforms.Linux, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:833
#115 2.403 [15] instantiate(::Pkg.Types.Context) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:795
#115 2.404 [16] #instantiate#169 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:791 [inlined]
#115 2.404 [17] instantiate() at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:791
#115 2.404 [18] top-level scope at none:1
#115 DONE 2.5s
Here is julia_instantiate.sh being RUN by the Dockerfile,
#!/bin/bash
cd ${WORKSPACEDIR}/src/;
folders=$(ls -d */)
echo ${folders}
for m in ${folders[@]}; do
cd "${WORKSPACEDIR}/src/${m}"
echo "instantiating: ${WORKSPACEDIR}/src/${m}"
julia --project=. -e "using Pkg; Pkg.instantiate(); using $(echo "${m}" | tr -d /); exit();"
done
- Docker image OS: Ubuntu 18.04
- Host OS: WSL2 Ubuntu 20.04
- Docker version: 20.10.6, build 370c289
- Julia version: 1.5.3
Julia issue #33593 seems related but it doesn't give me a work around.
Thoughts on how to work around this?
EDIT: Another point is that if I COPY julia_instantiate.sh into the docker image but don't execute it during the build, I get an image with the script and the Julia package source files in the image. If I run this container interactively and manually run julia_instantiate.sh it runs just fine. I run the container and attach as the same user that is baked into the docker image. So, it seams that the process fails only when the script is run by docker build.
NOTE: I've updated *julia_instantiate.sh to the minimal that I've been testing with. I've also added some additional information about the Dockerfile.