在Dockerfile构建过程中实例化Julia环境的问题



全部,

我正在为开发而设计的Docker容器中使用Julia。不同的开发人员在具有不同体系结构的各种主机上使用相同的Dockerfile。Julia安装在Docker映像中,但保存源代码的git-reos在运行时被装入卷。它运行得很好,只是每次启动容器时,我们都会成功地重新实例化Julia环境。因此,我试图在构建时将实例化的环境烘焙到Docker映像中。

在将Julia安装到Docker镜像中后,我将项目repos临时复制到镜像中的一个目录,该目录与运行时安装它们的位置相同。以下是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"]

为了帮助澄清更多。。。ARG环境变量是在启动构建时在命令行上定义的。这个脚本看起来像:

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}

当我试图在docker构建期间实例化项目时,我得到了以下错误,

#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

这里是julia_instantatie.sh由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镜像操作系统:Ubuntu 18.04
  • 主机操作系统:WSL2 Ubuntu 20.04
  • Docker版本:20.10.6,构建370c289
  • Julia版本:1.5.3

Julia问题#3593似乎有关联,但它并没有给我一个解决办法。

关于如何解决这个问题的想法?

编辑:另一点是,如果我将julia_instantiate.sh复制到docker映像中,但在构建过程中不执行它,我会在映像中获得一个带有脚本和julia包源文件的映像。如果我以交互方式运行这个容器,并手动运行julia_instantiate.sh,它运行得很好。我运行容器并作为烘焙到docker图像中的同一用户进行附加。因此,只有当脚本由docker构建运行时,该过程才会失败。

注意:我已经将*julia_instantiate.sh更新为我测试过的最小值。我还添加了一些关于Dockerfile的附加信息。

我发布了一个答案,但只是部分答案,因为我正在学习如何做同样的事情。我很难理解给定的dockerfile,我认为这种方法可能会使事情复杂化,并且很难找到错误。

这是一种方法(没有完整的文档(,它使我获得了一个运行中的julia映像,其中安装并实例化了包。

  1. 从基本映像构建并安装julia
  • 基于dockerhub的julia dockerfile
  • 这为其他基于各种包组合的julia工作人员提供了一个很好的起点
  • 我需要从AL2基础构建,而不是通常的公共julia dockerfile,这是单独执行这一步骤的唯一原因
  1. 从这个julia基本映像,为各种包运行Pkg.add,然后运行instance
  • 基于此话语线索和内部链接
# the important parts of dockerfile
RUN julia -e 'using Pkg; Pkg.add("Pipe", preserve=PRESERVE_DIRECT);'
RUN julia -e 'using Pkg; Pkg.add("DataFrames", preserve=PRESERVE_DIRECT);'
RUN julia -e 'using Pkg; Pkg.add("CSV", preserve=PRESERVE_DIRECT);'
RUN set -eux; 
mkdir "$JULIA_USER_HOME";
RUN julia -e 'using Pkg; Pkg.instantiate();'

这篇来自bkamins@的帖子;我在Julia中管理项目依赖性的实践;帮助很大,特别是Pkg.add.中可用的依赖关系保留命令

很抱歉,这不是一个完整的解决方案,我自己还没有完成这个过程,但这些都是我希望在开始时在SO上找到的。

最新更新