-
Notifications
You must be signed in to change notification settings - Fork 268
Add docs for Dev Containers #407
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
107 commits
Select commit
Hold shift + click to select a range
ac45984
Checkin work in progress
ruffsl 9de0304
Add section on Security
ruffsl 7827bc6
Add description of container runtime and runArgs
ruffsl 67a0f2e
Add to using dev container
ruffsl 16ff8e1
Add subsection on Terminals
ruffsl b05f070
Add subsection on Lifecycle
ruffsl 3bb9e62
Add reminder to Lifecycle about pushing to remote
ruffsl b3bded1
Add subsection on Rebuilding
ruffsl f0a0f2b
Rename file to own subtree
ruffsl 6880fe0
Enable markdown support for Sphinx
ruffsl f1aa71f
Add dev_containers to root index
ruffsl 293e78e
Fix missing URL
ruffsl 6601960
Spin out content into development guide
ruffsl 839e4d2
Add guides to index
ruffsl 9f7ed79
Fix subheading levels
ruffsl 2fd240c
Add reference to using remote docker host
ruffsl 2a70f54
Update section Getting stared
ruffsl c8a030d
Enalbe admonitions and callouts highlighting
ruffsl 024d0ed
Use tip admonition
ruffsl 1792267
Use node admonition
ruffsl 10c2c76
Rewording
ruffsl ec62d89
Fromatting
ruffsl 782bdde
Use caution admonition
ruffsl 26c0d5c
Use hint admonition
ruffsl e16df70
Wording
ruffsl e05586d
Wording
ruffsl 71b0484
Formatting
ruffsl 5ce6c6a
Add section intros
ruffsl d0651e1
Wording
ruffsl b9c4c2e
Add seealso callout for Nav2 CI
ruffsl a868f26
Add hint callout for colcon extentions
ruffsl d15bec2
Use attention admonition about runArgs
ruffsl 9b3deef
Update remarks on volumes
ruffsl 34098e5
Grammar
ruffsl d37e818
Update notes on current runArgs
ruffsl 8693a3e
Add seealso callout for details on used runArgs
ruffsl eced357
Update remark about volumes
ruffsl e20e522
Formatting
ruffsl 63dd66b
Sort Formatting
ruffsl 59e50f4
Install sphinx_copybutton
ruffsl 0ae0ca7
Simplify install instructions
ruffsl 6d98af1
Format install instructions
ruffsl e471b5e
Wording
ruffsl 898377d
Add missing annotating
ruffsl 1c3996f
Update build instructions
ruffsl 9edf13b
Update docker instructions
ruffsl 2fd7f7f
Default branch is sadly not named rolling
ruffsl a7362a9
Add descriptions for each build method
ruffsl 23c44ad
Wording
ruffsl a0775f2
Expand docker docs with links
ruffsl e146253
Formatting
ruffsl 4fa977b
Add note that rolling is tracked via main branch
ruffsl 7f645c9
Add tip for development workflow
ruffsl 276a2fa
Add attention to terminals
ruffsl 646bf96
Add hint to terminals
ruffsl bdd35ee
Add important to lifecycle
ruffsl 0545b81
Add caution to rebuilding
ruffsl 2f4eaf6
Add details to rebuilding without cache
ruffsl 801ab3d
Add caution to rebuilding without cache
ruffsl dd3add4
Add tip to rebuilding
ruffsl e298804
Split Visualization Guide into separate PR
ruffsl 113d8b6
Use seealso admonition
ruffsl a9159c8
Upgrade security caution to danger
ruffsl c1c01bb
Wording
ruffsl 2ab5264
Wording
ruffsl aee86e7
Add tip about logfile
ruffsl bc736e0
Typo
ruffsl aad97af
Comment out runArgs unintended side effects
ruffsl 076596f
Wording
ruffsl 7a536f8
Update requirements.txt
ruffsl 57ba320
Add new dependencies
ruffsl 737b7d6
Fix version for new dependencies
ruffsl 2f5dd35
Move development files
ruffsl 95ca826
Update README
ruffsl 453722b
Update Dockerfile
ruffsl cee4b24
Update CI
ruffsl 66f0fdb
Simplify Dockerfile
ruffsl d021595
Simplify apt install
ruffsl b6c878b
Expand apt install
ruffsl f53400d
Sort apt install
ruffsl 61752b8
Prune apt install
ruffsl 0126257
Update Dockerfile to match CI
ruffsl f0e2f3f
Fix working_directory
ruffsl 5b50364
Update attention
ruffsl dad2431
Avoid the use of export
ruffsl 0cb6fb3
Rewording
ruffsl e6aa6e4
Refactor build and devcontainer docs
ruffsl 9888bc7
Set language to english
ruffsl e385b01
Exclude README file
ruffsl a55e3f9
Orphan files not included in any toctree
ruffsl 7480513
Stage renaming links
ruffsl 7c54a15
Rename indexs and headings
ruffsl 316d497
Use globe for hidden toctree
ruffsl d221394
Add guide index for discoverability
ruffsl f9d1804
Reorder caution admonition as a TLDR
ruffsl a43c001
Add body text to index
ruffsl 265c2cb
Combine contribute into development guide
ruffsl 2f98a97
Add hidden toctree without maxdepth
ruffsl 42689a6
Use seealso admonition for dev container links
ruffsl ef233b2
Revert change to avoid duplicate toctree entries
ruffsl 99a806e
Instal sphinx-autobuild
ruffsl c3a1e43
Add make build task
ruffsl fbecd88
Add .dockerignore file
ruffsl 8bc021f
Add auto build option
ruffsl 33842a8
Show all warning
ruffsl 068a547
Add devcontainer config
ruffsl c95f117
Fix artifact path
ruffsl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| # Dev Containers | ||
|
|
||
| Alternatively you can use dev containers to build the project if you prefer a streamlined setup experience. This means you can use the same tools and dependencies as the rest of the team, including our Continuous Integration (CI) workflows, without worrying about installing dependencies on your host machine. Additionally, using Dev Containers makes it simple to switch between local or remote development environments, such as GitHub Codespaces. More info on Dev Containers can be found here: | ||
|
|
||
| - [Development Containers](https://containers.dev/) | ||
| - An open specification for enriching containers with development specific content and settings | ||
| - [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers) | ||
| - Learn how to use Visual Studio Code to develop inside a Docker container | ||
| - [GitHub Codespaces overview](https://docs.github.com/en/codespaces/overview) | ||
| - A development environment hosted in the cloud | ||
|
|
||
| ## What, why, how? | ||
|
|
||
| Lets briefly explain what dev containers are, why you should use them, and how they work. Here, we'll assume the use of VS Code, but the same concepts apply to other supporting tools and services, including alternative CLIs, IDEs, etc. such as: | ||
|
|
||
| - [Dev Container CLI](https://github.com/devcontainers/cli) | ||
| - A reference implementation for the open specification | ||
| - [JetBrains Space | Develop in Dev Environment](https://www.jetbrains.com/help/space/develop-in-a-dev-environment.html) | ||
| - Using Dev Containers with JetBrain based products | ||
| - [Supporting tools]() | ||
| - List of tools and services supporting the development container specification | ||
|
|
||
| ### What is a Dev Container? | ||
|
|
||
| A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine's operating system. | ||
|
|
||
| ### Why use a Dev Container? | ||
|
|
||
| A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS. | ||
|
|
||
| ### How do Dev Containers work? | ||
|
|
||
| When you open the project in VS Code, VS Code checks for the dev container configuration nested within the `.devcontainer` folder under the project's root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more. | ||
|
|
||
| This is quite similar to earlier tools used to customize and run docker containers for development: | ||
|
|
||
| - [rocker | ROS + Docker](https://github.com/osrf/rocker) | ||
| - A tool to run docker containers with overlays and convenient options for things like GUIs etc. | ||
| - Developed by [Open Robotics](https://www.openrobotics.org/) | ||
| - [ADE Development Environment](https://ade-cli.readthedocs.io/en/latest/) | ||
| - A modular Docker-based tool to ensure developers have a common, consistent development environment | ||
| - Developed by [Apex.AI](https://www.apex.ai/) | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| To use dev containers, you'll need the following: | ||
|
|
||
| - [Docker Engine](https://docs.docker.com/engine/install/) installed and running on the host machine | ||
| - [Visual Studio Code](https://code.visualstudio.com/) installed on any remote machine | ||
| - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension installed in VS Code | ||
|
|
||
| Alternatively, you could use GitHub Codespaces directly from the project repo: | ||
|
|
||
| - [Creating a codespace for a repository](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace-for-a-repository?tool=webui) | ||
| - How to create a codespace for repository via GitHub CLI, VS Code, or Web browser | ||
|
|
||
| ## Creating Dev Containers | ||
|
|
||
| Creating a dev container is as simple as opening the project in VS Code by either: following the prompts to reopen the project in a container, or explicitly opening the command palette and selecting `Remote-Containers: Reopen in Container`. This will create a new container, install any extensions specified in the project's default `.devcontainer/devcontainer.json` config file, and mount the project's root directory within the container. Once the container is created, VS Code will connect to it and you can start developing. | ||
|
|
||
| While you wait, feel free to stretch your legs, grab a coffee, or continue to read the following subsections to learn more about how dev containers are constructed. Note: opening the output log in VS Code allows you to watch how this sausage is made. | ||
|
|
||
| ### Building the image | ||
|
|
||
| When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project's Dockerfile builds `FROM`, as well as any tags or layers declared via `cacheFrom`, as specified in the chosen `devcontainer.json` config file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry. | ||
|
|
||
| Specifically, for this project, the default `devcontainer.json` file targets the `dever` stage within the project's root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn built `FROM` the `builder` stage, the stage that only includes the dependencies needed for building the project, as reused by the project's CI. For example, the `dever` stage modifies `/etc/bash.bashrc` to automatically source `install/setup.bash` from the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup. | ||
|
|
||
| To speed up the initial build, images layers from this `builder` stage are cached by pulling the same image tag used by the project's CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project's Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications. | ||
|
|
||
| Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additional [features](https://containers.dev/features) or customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container. | ||
|
|
||
| ### Starting the container | ||
|
|
||
| When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosen `devcontainer.json` config file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or `.devcontainer/` config. | ||
|
|
||
| Specifically, for this project, the default `devcontainer.json` config executes the `onCreateCommand` to initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project's source code are reflected in the container. This is especially useful for: | ||
|
|
||
| - IntelliSense | ||
| - Enables VS Code extensions to parse auto generated code | ||
| - Applicable for ROS package defining messages and services files | ||
| - Necessary for code modeling, navigation, and syntax highlighting | ||
| - Caching | ||
| - Enables Codespace Prebuilds to cache the workspace artifacts | ||
| - Applicable for reducing startup time when spawning new Codespaces | ||
| - Necessary for limiting costs from CPU and storage usage | ||
|
|
||
| While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next the `updateContentCommand` is executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during the `onCreateCommand`. This caching behavior also replicates the project's CI workflow. This is especially useful for: | ||
|
|
||
| - Branching | ||
| - Enables caching of workspace artifacts when switching between branches | ||
| - Applicable for reviewing pull requests without rebuilding entire container | ||
| - Necessary for reducing startup time when spawning new Codespaces | ||
|
|
||
| Finally, the `postCreateCommand` is executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user's environment to improve the development experience. | ||
|
|
||
| To speed up subsequent startups, volumes are mounted to the container store a persistent ccache directory, while the environment is set to enable [ccache](https://ccache.dev/) via [colcon mixins](https://github.com/colcon/colcon-mixin-repository). Additionally, the container is granted [privileged](https://docs.docker.com/engine/reference/commandline/run/#privileged) capabilities and connected using the [host](https://docs.docker.com/network/host/) network mode. This is especially useful for: | ||
|
|
||
| - Hybrid development | ||
| - Enables connecting ROS nodes external to the container | ||
| - Applicable for debugging or visualizing distributed systems | ||
| - Necessary for DDS discovery and shared memory transport | ||
| - Device connectivity | ||
| - Enables hardware forwarding from host machine to container | ||
| - Applicable for ROS package using sensors and actuators | ||
| - Necessary for some GPU drivers and USB devices | ||
|
|
||
| Note that these `runArgs` in the `devcontainer.json` config can be further customized, either expanded or or narrowed in scope, to better suit your desired development environment. The current configuration is merely the project default in order to be the most flexible and useful for the widest range of development use cases. | ||
|
|
||
| ## Using Dev Containers | ||
|
|
||
| Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project's root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project's dependencies, intellisense, linters, and other extensions pre-configured and ready to use. | ||
|
|
||
| So to build or test the project, simply open a terminal, cd to the root of the colcon workspace, and run the usual colcon commands. You may also want to incorporate the same colcon verbs used by the setup commands from the `devcontainer.json` config file to further automate your local development workflow. | ||
|
|
||
| ### Terminals | ||
|
|
||
| If you prefer using alternate terminal emulators, rather than the built-in VS Code terminal, you can also open a separate shell session directly using devcontainer CLI, or simply via docker exec. Note that new shell sessions started via `exec` will not automatically inherit the same environment setup by the `postCreateCommand` from the `devcontainer.json` config file. So you may need to manually source any necessary scripts, such as `install/setup.bash` from the underlay workspace. | ||
|
|
||
| - [Dev Container CLI](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) | ||
| - `devcontainer exec --workspace-folder <path-to-workspace> bash` | ||
| - [docker exec | ||
| ](https://docs.docker.com/engine/reference/commandline/exec/) | ||
| - `docker exec -it <container-id> bash` | ||
|
|
||
| ### Lifecycle | ||
|
|
||
| While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project's source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or the `devcontainer.json` config file, so that they can be easily reproduced and shared with others. This is particularly important when the host machine is inherently ephemeral as well, as the case may be when using cloud based environments such as Codespaces, so be sure to commit and push local changes to a remote repository: | ||
|
|
||
| - [The codespace lifecycle](https://docs.github.com/en/codespaces/getting-started/the-codespace-lifecycle) | ||
| - Maintain your data throughout the entire codespace lifecycle | ||
|
|
||
| ### Rebuilding | ||
|
|
||
| From time to time, you may need to rebuild the dev container, either because the base image, or `.devcontainer/` config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select the `Remote-Containers: Rebuild Container` command. For example, you may need to rebuild the dev container when: | ||
|
|
||
| - Pulling newer images from a container registry | ||
| - specifically, image tags built `FROM` in the Dockerfile | ||
| - or tags listed under `cacheFrom` in `devcontainer.json` | ||
| - periodically done manually to ensure local environment reflects CI | ||
| - Updating the dev container configuration | ||
| - specifically when modifying dependent stages in the `Dockerfile` | ||
| - or when modifying `./devcontainer` files and commands | ||
| - where build cache reuse correlates with severity of changes made | ||
|
|
||
| If necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting the `Remote-Containers: Rebuild Container Without Cache` command instead. Rebuilding without caching may be necessary when: | ||
|
|
||
| - Needing to update the base image | ||
| - specifically if dev container configurations remain unmodified | ||
| - to forcefully rerun a `RUN` directive in the Dockerfile | ||
| - such as unchanged `apt upgrade` or `rosdep update` commands | ||
|
|
||
| Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory. The management of these volumes is left for the developers discretion, and can be done via the [Docker CLI](https://docs.docker.com/engine/reference/commandline/cli/), or the [VS Code Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker). However, other projects may of course handle this differently, so be sure to check the `./devcontainer` configuration to inspect how various container resources may be managed. | ||
|
|
||
| ## Security | ||
|
|
||
| A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent. More info on trusting workspaces and extensions in general can be found here: | ||
|
|
||
| - [Workspace Trust](https://code.visualstudio.com/docs/editor/workspace-trust) | ||
| - VS Code user guid on trusting and configure workspaces | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.