I’m trying to create a docker container that has some of the packages already inst

I’m trying to create a docker container that has some of the packages already installed for later Julia execution.
The idea is that the current directory is something you want to run in docker, and it has a Project.toml (and maybe Manifest.toml).
You have a Dockerfile like this in the same directory:


# Not strictly needed as this is already the WORKDIR
WORKDIR /home/jovyan

COPY Project.toml .

RUN julia --project=. -e "using Pkg; Pkg.instantiate()"```
Now you would like to create an image from this, and when it’s later run it already has the required packages. However, it does not work.
```docker build -t julia-notebook:latest . 
Sending build context to Docker daemon  41.47kB
Step 1/4 : FROM jupyter/datascience-notebook:latest
 ---> a665c8ddeb27
Step 2/4 : WORKDIR /home/jovyan
 ---> Using cache
 ---> 238e157c2ad9
Step 3/4 : COPY Project.toml .
 ---> Using cache
 ---> 0a2f8af5010d
Step 4/4 : RUN julia --project=. -e "using Pkg; Pkg.instantiate()"
 ---> Running in 0423f039f9de
   Updating registry at `/opt/julia/registries/General`
######################################################################## 100.0%
  Installed RollingFunctions ───────────── v0.6.2
  Installed ThreadsX ───────────────────── v0.1.7
...several lines deleted...
  Installed IterTools ──────────────────── v1.3.0
  Installed GR ─────────────────────────── v0.53.0
ERROR: SystemError: opening file "/home/jovyan/Project.toml": Permission denied
Stacktrace:
 [1] systemerror(::String, ::Int32; extrainfo::Nothing) at ./error.jl:168
 [2] #systemerror#48 at ./error.jl:167 [inlined]
 [3] systemerror at ./error.jl:167 [inlined]
 [4] open(::String; lock::Bool, read::Nothing, write::Nothing, create::Nothing, truncate::Bool, append::Nothing) at ./iostream.jl:284
 [5] open(::Pkg.Types.var"#31#33"{Base.GenericIOBuffer{Array{UInt8,1}}}, ::String; kwargs::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:truncate,),Tuple{Bool}}}) at ./io.jl:323
 [6] write_project at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/project.jl:180 [inlined]
 [7] write_project(::Pkg.Types.Project, ::String) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/project.jl:175
 [8] write_project at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/project.jl:173 [inlined]
 [9] write_env(::Pkg.Types.EnvCache; update_undo::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1366
 [10] write_env at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1366 [inlined]
 [11] up(::Pkg.Types.Context, ::Array{Pkg.Types.PackageSpec,1}, ::Pkg.Types.UpgradeLevel) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Operations.jl:1226
 [12] up(::Pkg.Types.Context, ::Array{Pkg.Types.PackageSpec,1}; level::Pkg.Types.UpgradeLevel, mode::Pkg.Types.PackageMode, update_registry::Bool, 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:245
 [13] #up#38 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:68 [inlined]
 [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:810
 [15] instantiate(::Pkg.Types.Context) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:795
 [16] #instantiate#169 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:791 [inlined]
 [17] instantiate() at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/API.jl:791
 [18] top-level scope at none:1
The command '/bin/bash -o pipefail -c julia --project=. -e "using Pkg; Pkg.instantiate()"' returned a non-zero code: 1

So instantiating it tries to write Project.toml, I think, and it does not work because it is in a read-only layer created earlier by the COPY command.
Any ideas? Adding the packages to the default project would be fine since the image will only ever have one Julia project in it.

Note that the poster on Slack cannot see your response here on Discourse. Consider answering the question there or pinging the poster here on Discourse so they see the reponse.
(Original message :slack:)

1 Like

The problem is that the Dockerfile(s) created by the Jupyter project use USER root, which causes COPY and RUN to execute as different users in this Dockerfile.

(base) jovyan@c10d47473a48:~$ ls -l
total 8
-rw-r--r-- 1 root   root    63 Jan 31 14:03 Project.toml
drwsrwsr-x 2 jovyan users 4096 Jan 28 16:43 work
(base) jovyan@c10d47473a48:~$ whoami
jovyan

This Dockerfile works:

FROM jupyter/datascience-notebook:latest
WORKDIR /home/jovyan
USER root
COPY Project.toml .
RUN julia --project -e "using Pkg; Pkg.instantiate();"
RUN julia -e "using Pkg; Pkg.status()"

The notebook is not run as root due to start-notebook.sh.

3 Likes