Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Add dev container configuration #12306

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

hoechenberger
Copy link
Member

@hoechenberger hoechenberger commented Dec 18, 2023

๐Ÿ‘ฉโ€๐Ÿ’ป The experience I'm implementing here

Screenshot 2023-12-18 at 17 13 08
Screen.Recording.2023-12-18.at.15.29.08.mov

๐Ÿ“š Background

In the past year, I moved almost all my development work into dev containers.

A development container (or dev container for short) allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing. Dev containers can be run locally or remotely, in a private or public cloud, in a variety of supporting tools and editors.

Until recently, one of the few development workflows I had not yet transitioned to use dev containers was MNE-Python. Reason was that the interactive figures don't work well in a notebook or web browser, and I didn't want to run an X server on my host just to display the figures.

๐Ÿ’ก Solution

I created a dev container configuration that deploys a remote resktop feature. It allows for a remote connection via a VNC client, or via the web browser. Browser-based access even works inside VS Code with the built-in Simple Browser.

The dev container runs on Debian 11, installs MNE-python via conda-forge, followed by a pip-based editable install of the version in the checked-out repository.

๐ŸŽฏ Scope & target audience

  • Provide a seamless, virtually setup-free development environment to any interested party on all supported platforms (macOS, Windows, Linux)
  • Allow for development via GH Codespaces.

๐Ÿ”ฎ Future plans

  • Use dev container as a basis to deliver containers of stable MNE releases to end-users.
  • Add a feature that installs FreeSurfer.
  • Add a feature that downloads the sample and testing datasets.

๐Ÿƒโ€โ™€๏ธ Using the dev container

You need

  • Docker Desktop
  • VS Code with the Dev Containers extension
  • a copy of this repository branch

Open the repository in VS Code and click on Reopen in Container in the bottom right.

The Debian docker image and dev container features including MNE will be downloaded and installed. Lastly, an editable install of MNE will be carried out.

The VNC server will be exposed on localhost:5901 (you can connect to it with any VNC client, e.g. Screen Sharing.app on macOS), and the web server can be reached on http://localhost:6080. The password is vscode.

You can now start developing and using MNE-Python. Interactive figures will appear on the screen exposed via the VNC server.

All development dependencies are installed (incl. pre-commit hooks, pytest etc.), and the editor is set to auto-format code via Ruff on saving.

The host SSH agent's socket is transparently forwarded into the container, meaning you should be able to use SSH immediately without requiring any further configuration.

The host's git configuration is copied to the container as well, so your name and email address are set correctly, too.

โœ‹ Limitations

I currently enforce running an AMD64 Debian image on all platforms, including Apple Silicon. The native ARM64 wouldn't work as MNE-Python cannot be installed from conda-forge on this platform, as the migration of aarch64dependencies is still ongoing. To avoid this, all deps could be potentially installed from PyPI via pip, but I haven't tried this yet.

โ“Thoughts?

What do you all think?

cc @cbrnr @britta-wstnr @agramfort @sappelhoff

@@ -0,0 +1,3 @@
# This Dockerfile is currently only used to enforce use of x86 image on ARM64 CPUs (Apple Silicon)
# See aarch64 migration on https://conda-forge.org/status/, which is currently blocking us.
FROM --platform=amd64 mcr.microsoft.com/devcontainers/base:debian-11
Copy link
Member Author

Choose a reason for hiding this comment

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

enforcing AMD64 platform here

Copy link

Choose a reason for hiding this comment

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

Why base:debian-11 instead of base:ubuntu-22.04? My undestanding is that it can be very painful to get some packages (latest or not) in Debian.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ubuntu 22 and Debian 12 ship with OpenSSL 3, which dropped support for some older, insecure algorithms.

Our corporate firewall still injects some of these older certs in some places, so certain encrypted connections fail to be established. Sucks but that's how it is currently, not just for me.

All packages we need seem to be available in recent-enough versions. Is there anything particular you expect to be problematic? Remember we're not trying to provide an all-purpose dev environment here, only one specifically tailored for MNE development.

Many tools are available as dev container features too, so we're somewhat independent from the base OS anyway. And we can install binaries nova conda.

Comment on lines +13 to +14
"packages": "mesa-utils,libegl1,^libxcb.*-dev,libx11-xcb-dev,libglu1-mesa-dev,libxrender-dev,libxi-dev,libxkbcommon-dev,libxkbcommon-x11-dev"
},
Copy link
Member Author

Choose a reason for hiding this comment

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

this could probably be trimmed down a little? not sure.

@hoechenberger
Copy link
Member Author

The password for VNC access is vscode.

@hoechenberger hoechenberger marked this pull request as ready for review December 19, 2023 08:25
Copy link
Member

@drammock drammock left a comment

Choose a reason for hiding this comment

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

I like this idea / initiative! I've left mostly questions and a few comments, so I can understand better how the config works.

"build": { "dockerfile": "Dockerfile" },
"containerEnv": {
"PYTHONNOUSERSITE": "true", // Make Python ignore the user's site-packages folder if it exists
"XDG_RUNTIME_DIR": "/home/vscode/.cache/xdgr"
Copy link
Member

Choose a reason for hiding this comment

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

I stumbled on this line, until I realized that "vscode" is being set as the username in the container. Will it still work if we change it to "mneuser" or similar (here and on line 131)? I.e., something that is more obviously an (arbitrary) username?

Copy link
Member Author

Choose a reason for hiding this comment

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

The base image I'm using sets up the vscode user by default. There's been discussions on changing this to something more generic like devcontainer, but this still remains to be implemented:

devcontainers/images#145

Changing it to a custom name like mneuser would require changes to the Dockerfile and potentially some of the features we're using; hence I'd like to refrain from doing that โ€“ there's no need to, you basically never deal with that username anyway outside of this very line here :)

I however changed the VNC password to mne in 54b159b

Copy link
Member Author

Choose a reason for hiding this comment

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

I may have found a workaround but I need to test it a bit first. It may make it harder for me to get the dev container to work behind our corporate firewall, where I need to inject our self-signed SSL certs via a custom feature first. I want to make sure this doesn't become even more difficult or impossible if I change the default user name here.

Copy link
Member

Choose a reason for hiding this comment

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

Ok but don't spend too much effort on it, it's a minor maintainer-facing improvement right (user will not notice)?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's basically irrelevant to users of the container, yes

Copy link
Member Author

Choose a reason for hiding this comment

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

Username is now mne-user

.devcontainer/devcontainer.json Outdated Show resolved Hide resolved
Comment on lines 27 to 30
// Zsh plugins
"ghcr.io/devcontainers-contrib/features/zsh-plugins:0": {
"plugins": "zsh-autosuggestions zsh-syntax-highlighting history-substring-search",
"omzPlugins": "https://github.com/zsh-users/zsh-autosuggestions https://github.com/zsh-users/zsh-syntax-highlighting"
Copy link
Member

Choose a reason for hiding this comment

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

why are these needed? Will the user ever access a terminal in the container (and if so, won't it be a BASH terminal by default?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, of course :) It's a complete development environment, and if you open a terminal, it will open a "remote" shell inside the Docker container.

The default shell is zsh with oh-my-zsh.

I'm trying to provide a nice and comfy shell experience through these plugins.

Copy link
Member

Choose a reason for hiding this comment

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

I'm trying to provide a nice and comfy shell experience through these plugins.

Another word for "comfy" is "familiar". I don't necessarily object to including zsh alongside bash but I'm dubious about making zsh the default here.

Copy link

Choose a reason for hiding this comment

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

MacOS users have zsh as the default shell and zsh is very close to bash.

Copy link
Member

Choose a reason for hiding this comment

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

yes, I know that since 2019 macOS uses zsh as the default shell. And I've heard that they're similar. What I'm questioning is why tailor the experience in a linux container to feel familiar to macOS users. Sticking with BASH seems like the natural default choice, and deviation from that feels like it needs to be justified.

Copy link
Member Author

Choose a reason for hiding this comment

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

Both shells are first-class citizens in the MS dev containers. By default, both are shipped, hence I'm shipping both too. The plugins listed here make the zsh experience better and superior to the Bash experience. I have not yet decided which shell shall be the default one. However, I'm surprised this seems to be so controversial. VS Code clearly displays which shell is being used, and when spawning a new terminal, one can select the shell from a dropdown menu. Besides, I don't see how the choice of shell matters as long as one doesn't do shell programming; and this is an MNE dev container, no generic Linux Shell Programming dev container. Like I said, I haven't decided yet which default I think would be best; but It's quite obvious to me though that the zsh prompt looks better and the shell provides more help during interactive use (history substring search being one of those invaluable features; git support being another).

Copy link
Member

Choose a reason for hiding this comment

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

I have not yet decided which shell shall be the default one.

This is news to me; you originally set zsh as default (which I noticed at the time), then removed that setting in 7d5c6a2 after my earlier comments. It seems a bit disingenuous to now say "why is this so controversial, they're both included and I haven't chosen a default".

That said, I'm happy if both are included and it's easy (and documented) for users to switch the shell they get in their container. Ideally this would be a one-time config (not something that needs doing every time the container is launched) if that's possible

Copy link
Member Author

Choose a reason for hiding this comment

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

This is news to me; you originally set zsh as default (which I noticed at the time), then removed that setting in 7d5c6a2 after my earlier comments

Ah, I see!! No, this was actually a misunderstanding. The default login shell always was Bash, and the setting you're referring to controls which shell should be spawned by default when creating a new terminal without explicitly selecting a shell. This was in fact an accidental setting that I copied over from another dev container config I'm working with. But this setting never changed the (login) default shell to zsh, nor dropped bash or something :) I had however forgotten to properly set up mamba and conda for bash โ€“ย something I realized and fixed after your comment / question.

That said, I'm happy if both are included and it's easy (and documented) for users to switch the shell they get in their container. Ideally this would be a one-time config (not something that needs doing every time the container is launched) if that's possible

Yep, I'm open for this! for now I'm really still trying to make things work and experimenting a bit! Let's save the heated debates for later! ๐Ÿ˜๐Ÿค—

Oh and, happy holidays to you all!!!

Comment on lines +37 to +39
// Configure properties specific to VS Code.
"vscode": {
"settings": {
Copy link
Member

Choose a reason for hiding this comment

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

seems like fertile ground for bikeshedding. Is there a way for the container to pick up the user's local settings? If not, then can you indicate which of these settings are truly necessary for the container to work, which are not necessary but clearly a good idea (e.g., don't restore port forwards?), and which are your preferences (perhaps "format on type" fits here)?

.devcontainer/devcontainer.json Outdated Show resolved Hide resolved
@@ -97,6 +97,7 @@ cover
.venv/
venv/
*.json
!/.devcontainer/devcontainer.json
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
!/.devcontainer/devcontainer.json
!.devcontainer/devcontainer.json

Copy link
Member Author

Choose a reason for hiding this comment

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

I actually wanted to be explicit, hence the "full" path specification here

@hoechenberger
Copy link
Member Author

Thanks for you feedback, @drammock
I will respond to your remaining comments later tonight or tomorrow

@hoechenberger hoechenberger added this to the 1.7 milestone Apr 9, 2024
@hoechenberger
Copy link
Member Author

would be good to get this "into" 1.7, but i'm not sure if i'll be able to finish it in time

i know it's devs-only but it would be nice to have a reference to this in the 1.7 stable docs

@larsoner
Copy link
Member

larsoner commented Apr 9, 2024

would be good to get this "into" 1.7, but i'm not sure if i'll be able to finish it in time

In this case let's not mark it for 1.7 -- let's only mark the things that are blockers for release (which should happen this week ideally). If it gets merged in time though that's great (nothing stopping it if you can get it done)!

@larsoner larsoner modified the milestones: 1.7, 1.8 Apr 9, 2024
@hoechenberger
Copy link
Member Author

ok I'm fine with that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants