Skip to content
This repository has been archived by the owner on Nov 30, 2023. It is now read-only.

Add Julia devcontainer #450

Merged
merged 3 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions containers/julia/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "Julia",
"image": "ghcr.io/julia-vscode/julia-devcontainer",
"extensions": ["julialang.language-julia"],
"postCreateCommand": "julia --project=. -e 'using Pkg; if (isfile(joinpath(pwd(),\"Manifest.toml\")) || isfile(joinpath(pwd(),\"JuliaManifest.toml\"))) && (isfile(joinpath(pwd(),\"Project.toml\")) || isfile(joinpath(pwd(),\"JuliaProject.toml\"))); Pkg.instantiate(); end'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we're trying to keep the postCreateCommand as something developers can use as needed. These files are dropped into an existing project. Is this something that every developer would want to do with source files that already exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this makes sense for everyone. It essentially just makes sure all the packages that are specified as a dependency in the root Julia configuration file in the repo are actually installed on the machine and available right away.

I guess in theory we could also try to put this into a docker script file, but then we would lose the ability to use the pre existing julia image files and instead would end up using building a new image for every single repo, which seems a lot less nice from a performance point of view?

We've been doing a very similar thing in the existing Julia mybinder.org integration for a long time and it seems to be what users want.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there's a bit of a balance between keeping it simple and getting people started that varies between ecosystems.

Generally we've been adding Dockerfiles to help people get started on adding their own contents to the image. (For example, this Dockerfile). That's not strictly required though - it depends on how likely someone is to want to do something like this.

One thing I did notice, however, is git is not present in the base Julia image. That's a pretty common dependency. There is a script that can be used that pulls in common dependencies including git. You are right that it can increase the time it takes to get the container up, however. You can default to not installing zsh and not upgrading packages to help there a bit. e.g.

# This Dockerfile adds a non-root user with sudo access. Update the “remoteUser” property in
# devcontainer.json to use it. More info: https://aka.ms/vscode-remote/containers/non-root-user.
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Options for common setup script
ARG INSTALL_ZSH="false"
ARG UPGRADE_PACKAGES="false"
ARG COMMON_SCRIPT_SOURCE="https://github.com/microsoft/vscode-dev-containers/master/script-library/common-debian.sh"
ARG COMMON_SCRIPT_SHA="dev-mode"
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
RUN apt-get update \
    && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends curl ca-certificates 2>&1 \
    && curl -sSL  ${COMMON_SCRIPT_SOURCE} -o /tmp/common-setup.sh \
    && ([ "${COMMON_SCRIPT_SHA}" = "dev-mode" ] || (echo "${COMMON_SCRIPT_SHA} */tmp/common-setup.sh" | sha256sum -c -)) \
    && /bin/bash /tmp/common-setup.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \
    && rm /tmp/common-setup.sh \
    && apt-get autoremove -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*

The package upgrade is mainly something we have for scenarios where a downstream image is actually generated so security patches are picked up before its published.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, git is a good point! I'll try to figure out whether there is some pre-built image for julia that includes git, that would give us the fastest story, right? If not, I'll look into the custom dockerfile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or would it make sense that we (the Julia extension for VS Code) publish our own julia-devcontainer image for this scenario? That way we could include anything we think is useful, but avoid the extra time to build a new docker image every time a user instantiates a new devcontainer?

I guess this is a scenario where microsoft/vscode-remote-release#3441 would also help: you (the codespace implementation) could actually cache the docker image that gets build by a particular devcontainer definition that is in the central repo and then reuse that docker image for any user instance that references it. mybinder.org has a pretty neat design where various docker images get cached at various points, there might be some good ideas there.

Copy link
Member

@Chuxel Chuxel Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publishing your own image makes a ton of sense since that gives you control over when updates need to happen to the image. There's a number of other examples of this in the repository - e.g. Puppet, Salesforce, Azure Functions.

The thing about microsoft/vscode-remote-release#3441 that is not covered by the image alone is the various devcontainer.json settings. In some cases these can be more involved, so we've considered the idea of a "inheritance" for it where you can start from a definition and then override, but that doesn't diminish the value of a published image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, the custom image works great. I just need to figure out how we can update it regularly and make those kinds of aspects a bit more stable, and then I'll update this PR here. Thanks for all the help and guidance!

}
6 changes: 6 additions & 0 deletions containers/julia/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
../README.md
../test-project
../.vscode/launch.json
../.vscode/launch.test.json
../.vscode/settings.json
../.vscode/tasks.json
39 changes: 39 additions & 0 deletions containers/julia/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Julia

## Summary

*Develop Julia applications.*

| Metadata | Value |
|----------|-------|
| *Contributors* | David Anthoff, github.com/davidanthoff |
| *Definition type* | Image |
| *Works in Codespaces* | Yes |
| *Container host OS support* | Linux |
| *Languages, platforms* | Julia |

## Using this definition with an existing folder

Just follow these steps:

1. If this is your first time using a development container, please follow the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started) to set up your machine.

2. To use VS Code's copy of this definition:
1. Start VS Code and open your project folder.
2. Press <kbd>F1</kbd> select and **Remote-Containers: Add Development Container Configuration Files...** from the command palette.
3. Select the Dart definition.

3. To use latest-and-greatest copy of this definition from the repository:
1. Clone this repository.
2. Copy the contents of this folder in the cloned repository to the root of your project folder.
3. Start VS Code and open your project folder.

4. After following step 2 or 3, the contents of the `.devcontainer` folder in your project can be adapted to meet your needs.

5. Finally, press <kbd>F1</kbd> and run **Remote-Containers: Reopen Folder in Container** to start using the definition.

## License

Copyright (c) Microsoft Corporation. All rights reserved.

Licensed under the MIT License. See [LICENSE](https://github.com/Microsoft/vscode-dev-containers/blob/master/LICENSE).
50 changes: 50 additions & 0 deletions containers/julia/test-project/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash -i
cd $(dirname "$0")

# -- Utility functions --
if [ -z $HOME ]; then
HOME="/root"
fi

FAILED=()

check() {
LABEL=$1
shift
echo -e "\n🧪 Testing $LABEL: $@"
if $@; then
echo "🏆 Passed!"
else
echo "💥 $LABEL check failed."
FAILED+=("$LABEL")
fi
}

checkMultiple() {
PASSED=0
LABEL="$1"
shift; MINIMUMPASSED=$1
shift; EXPRESSION="$1"
while [ "$EXPRESSION" != "" ]; do
if $EXPRESSION; then ((PASSED++)); fi
shift; EXPRESSION=$1
done
check "$LABEL" [ $PASSED -ge $MINIMUMPASSED ]
}

checkExtension() {
checkMultiple "$1" 1 "[ -d ""$HOME/.vscode-server/extensions/$1*"" ]" "[ -d ""$HOME/.vscode-server-insiders/extensions/$1*"" ]" "[ -d ""$HOME/.vscode-test-server/extensions/$1*"" ]"
}

# -- Actual tests --
checkMultiple "vscode-server" 1 "[ -d ""$HOME/.vscode-server/bin"" ]" "[ -d ""$HOME/.vscode-server-insiders/bin"" ]" "[ -d ""$HOME/.vscode-test-server/bin"" ]"
check "julia" julia --version

# -- Report results --
if [ ${#FAILED[@]} -ne 0 ]; then
echo -e "\n💥 Failed tests: ${FAILED[@]}"
exit 1
else
echo -e "\n💯 All passed!"
exit 0
fi