Skip to content

Add container to existing project

Thibaut Lamadon edited this page Mar 18, 2024 · 1 revision

Worked Example

Suppose we have a julia project on our computer which we want to containerize now. The project is composed of several files, and comes as a standard julia package. In fact, we will use the Example.jl package to illustrate.

  1. Create the package: this would be your initial workflow where you create your package locally. You can skip this step if you already have a package. I will clone the Example.jl package to illustrate.
floswald@PTL11077 ~> cd # going home
floswald@PTL11077 ~> git clone git@github.com:JuliaLang/Example.jl.git 
floswald@PTL11077 ~> ls Example.jl/                                                               
LICENSE.md    Project.toml  README.md     docs/         src/          test/

Notice that at this point we are, of course, still on our local machine, using our local OS, and we are called by our usual user name:

floswald@PTL11077 ~> echo $USER                                                                               
floswald
floswald@PTL11077 ~> uname                                                                                    
Darwin
  1. Let's add a function to the package. We will add a function that prints the current user name and OS.
# adding this to src/Example.jl
function print_user()
    println("I am $(Base.Sys.CPU_NAME) on $(Base.Sys.KERNEL)")
end

  1. See whether it works locally. We can start julia and run the function.
floswald@PTL11077 ~> julia --project=Example.jl -e 'using Example; Example.print_user()'
I am apple-m1 on Darwin

Ok, so far so good. Now we want to containerize this.

  1. Copy the .devcontainer folder from this repo to the project root (i.e. ~/Example.jl in this case). This folder contains two files, the container description devcontainer.json and a Dockerfile we wrote that builds the container image with all necessary dependencies to run Julia.
floswald@PTL11077 ~> cd Example.jl/
# I stored dev-container-julia in ~/git/dev-container-julia, so I copy it from there
floswald@PTL11077 ~/Example.jl> cp -r ../git/dev-container-julia/.devcontainer .
  1. Make sure your docker daemon is running. You need to install docker from https://www.docker.com and start it.

  2. Open the Example.jl project in VSCode. VSCode will detect the .devcontainer folder and ask you whether you want to open it in a container. Click yes. Alternatively, if you have VSCode still open, observe that now you have the .devcontainer folder in the explorer. Go into the command palette with cmd+shift+p and type "rebuild and reopen in container". Click on show log to see what is going on: We are pulling a ubuntu image from the docker hub, and then we are building the container image on top of it. This will take a while the first time around.

  3. Check your docker hub: our julia dev container is now running. Go back to VSCode.

  4. You see exactly the same content as before: those are the same files you created. Our print_user function is still there. But look in the terminal below: the current user is called jovyan, and the heading of the window is different now:

  1. Let's run our print_user function:
    jovyan ➜ ~/workspace (master) $ julia --project=. -e 'using Example; Example.print_user()'
    I am generic on Linux
  2. Notice that the complete file structure is preserved from before. Like for example, the remote host for this repository is still the original one:
    jovyan ➜ ~/workspace (master) $ git remote --v
    origin  git@github.com:JuliaLang/Example.jl.git (fetch)
    origin  git@github.com:JuliaLang/Example.jl.git (push)
  3. How do work with this now? For one, you can just call julia from the built-in terminal, we have done above. But that's not all. You can also install the julia-vscode extension into the container instance, by clicking left in vscode on the extensions icon and search for julia. After that, you can start an integrated julia REPL exactly as you would on your local machine. For example here, I added Revise to the Example project, load it, and added and modified a function called print_date on the fly without reloading anything.

Clone this wiki locally