Skip to content

Update template, add features and image metadata info #21

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 1 commit into from
Jan 3, 2023
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
18 changes: 14 additions & 4 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp/.devcontainer/base.Dockerfile
# [Choice] Debian / Ubuntu version (use Debian 11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
ARG VARIANT=debian-11
FROM mcr.microsoft.com/devcontainers/cpp:0-${VARIANT}
FROM mcr.microsoft.com/devcontainers/cpp:0-debian-11

ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="none"

# Optionally install the cmake for vcpkg
COPY ./reinstall-cmake.sh /tmp/

RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \
chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \
fi \
&& rm -f /tmp/reinstall-cmake.sh

# [Optional] Uncomment this section to install additional vcpkg ports.
# RUN su vscode -c "${VCPKG_ROOT}/vcpkg install <your-port-name-here>"

# [Optional] Uncomment this section to install additional packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
Expand Down
27 changes: 11 additions & 16 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "C++",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
// Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
"args": { "VARIANT": "debian-11" }
"dockerfile": "Dockerfile"
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],

Choose a reason for hiding this comment

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

I had been curious about what this was meant to do when I saw it in the past. It looks like it's useful to enable some developer tools on a Docker container, but I agree it shouldn't be in this example.

(see https://forums.docker.com/t/security-implications-of-cap-add-sys-ptrace-security-opt-seccomp-unconfined-needed-for-rr/49816)

Copy link
Member Author

@Chuxel Chuxel Dec 23, 2022

Choose a reason for hiding this comment

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

This is required to enable ptrace-based debugging which, unless something has chainged, is needed to debug C++. This is now set on the image. https://github.com/devcontainers/images/blob/main/src/cpp/.devcontainer/devcontainer.json#L6-L7

Go and Rust also need this, but things like Python, C#, and Node do not. It's a common "gotcha".



// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-vscode.cpptools"
Copy link

@michaelbprice michaelbprice Dec 21, 2022

Choose a reason for hiding this comment

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

This breaks the OOBE for this example.

Recommend ms-vscode.cpptools-extension-pack instead, otherwise the user will get a toast notification for "C++ tools" that wants to install the extension pack.

See also comments on the related documentation update.

Copy link
Member Author

@Chuxel Chuxel Dec 23, 2022

Choose a reason for hiding this comment

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

It actually doesn't if you test out the example. The image now includes this extension as explained in the README updates. This part of the new image metadata capability for Dev Containers.

We could, however, flip to the extension pack in the image. Right now, its CMake and C++: https://github.com/devcontainers/images/blob/main/src/cpp/.devcontainer/devcontainer.json#L14-L15

Choose a reason for hiding this comment

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

So, if I understand this correctly then, the container image in the FROM line of the Dockerfile is constructed from a dev container spec at that link.

Do you have a link to the documentation for the new image metadata capability for Dev Containers? I'm not familiar with it.

When I tested the example, I got a VSCode notification asking to install C/C++ extensions. After I manually added back ms-vscode.cpptools I expected that to go away, but it didn't, which is when I realized that that notification goes away with the extension pack instead. That might be worth improving on for the C++ extension (@AlexandraKemperMS).

I let an extra variable sneak into my test. :)

FWIW, I'm not crazy about hiding that implementation detail. If we expect people to learn something other than "I guess it does work." from these repositories, they may not immediately follow the leap towards the extensions being installed in the base image via a different devcontainer.json file. For me, who has some experience with using them, it really did feel like something critically important was just missing.

Is there some advantage to putting those in the base image that I'm not understanding?

Copy link
Member Author

@Chuxel Chuxel Dec 24, 2022

Choose a reason for hiding this comment

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

Make sure you are on the latest version of VS Code and the extension. This is a new capability. I can double check.

The link to the docs is in the README. https://devcontainers.github.io/implementors/spec/ has the details on processing and https://devcontainers.github.io/implementors/json_reference/ annotates which properties are supported.

The goal is to prevent config drift by keeping the settings needed for the image with the image. It also allows mass config updates across many repos at once which has been a common ask. Finally it simplifies reuse since you can just ref an image directly if you prefer.

"streetsidesoftware.code-spell-checker"
]
}
},
}

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "gcc -v",

// Comment out this line to run as root instead.
"remoteUser": "vscode"

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
58 changes: 58 additions & 0 deletions .devcontainer/reinstall-cmake.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash

Choose a reason for hiding this comment

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

This file is not necessary for this example and adds a lot of extra complexity. The C++ code does not use CMake and works just fine with the both the base C++ extension and the C++ extension pack (which includes the CMake extension... but not CMake...).

Copy link
Member Author

@Chuxel Chuxel Dec 23, 2022

Choose a reason for hiding this comment

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

Vcpkg's requirements in some cases require a more recent version of cmake than is in the distro itself. This was added to the template when Vcpkg was added to the image. I think Debian 11 has a recent enough cmake though, so we could remove it here.

https://github.com/devcontainers/images/blob/main/src/cpp/.devcontainer/Dockerfile#L11-L22

Choose a reason for hiding this comment

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

The example source code does not use vcpkg either though.

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 image is general purpose not specific to the sample. The README at the top of devcontainer.json points to the general purpose template. Happy to take a PR to illustrate its use if you would like.

#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
set -e

CMAKE_VERSION=${1:-"none"}

if [ "${CMAKE_VERSION}" = "none" ]; then
echo "No CMake version specified, skipping CMake reinstallation"
exit 0
fi

# Cleanup temporary directory and associated files when exiting the script.
cleanup() {
EXIT_CODE=$?
set +e
if [[ -n "${TMP_DIR}" ]]; then
echo "Executing cleanup of tmp files"
rm -Rf "${TMP_DIR}"
fi
exit $EXIT_CODE
}
trap cleanup EXIT


echo "Installing CMake..."
apt-get -y purge --auto-remove cmake
mkdir -p /opt/cmake

architecture=$(dpkg --print-architecture)
case "${architecture}" in
arm64)
ARCH=aarch64 ;;
amd64)
ARCH=x86_64 ;;
*)
echo "Unsupported architecture ${architecture}."
exit 1
;;
esac

CMAKE_BINARY_NAME="cmake-${CMAKE_VERSION}-linux-${ARCH}.sh"
CMAKE_CHECKSUM_NAME="cmake-${CMAKE_VERSION}-SHA-256.txt"
TMP_DIR=$(mktemp -d -t cmake-XXXXXXXXXX)

echo "${TMP_DIR}"
cd "${TMP_DIR}"

curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_BINARY_NAME}" -O
curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_CHECKSUM_NAME}" -O

sha256sum -c --ignore-missing "${CMAKE_CHECKSUM_NAME}"
sh "${TMP_DIR}/${CMAKE_BINARY_NAME}" --prefix=/opt/cmake --skip-license

ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-cpp)

A **development container** is a running [Docker](https://www.docker.com) container with a well-defined tool/runtime stack and its prerequisites. You can try out development containers with **[GitHub Codespaces](https://github.com/features/codespaces)** or **[Visual Studio Code Dev Containers](https://aka.ms/vscode-remote/containers)**.
A **development container** is a running container with a well-defined tool/runtime stack and its prerequisites. You can try out development containers with **[GitHub Codespaces](https://github.com/features/codespaces)** or **[Visual Studio Code Dev Containers](https://aka.ms/vscode-remote/containers)**.

This is a sample project that lets you try out either option in a few easy steps. We have a variety of other [vscode-remote-try-*](https://github.com/search?q=org%3Amicrosoft+vscode-remote-try-&type=Repositories) sample projects, too.

Expand All @@ -12,8 +12,9 @@ This is a sample project that lets you try out either option in a few easy steps

### GitHub Codespaces
Follow these steps to open this sample in a Codespace:
1. Click the Code drop-down menu and select the **Open with Codespaces** option.
1. Select **+ New codespace** at the bottom on the pane.
1. Click the **Code** drop-down menu.
2. Click on the **Codespaces** tab.
3. Click **Create codespace on main** .

For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace).

Expand Down Expand Up @@ -41,21 +42,29 @@ Follow these steps to open this sample in a container using the VS Code Dev Cont

Once you have this sample opened, you'll be able to work with it like you would locally.

> **Note:** This container runs as a non-root user with sudo access by default. Comment out `"remoteUser": "vscode"` in `.devcontainer/devcontainer.json` if you'd prefer to run as root.

Some things to try:

1. **Edit:**
- Open `main.cpp`
- Try adding some code and check out the language features.
- Notice that the C++ extension is already installed in the container since the `.devcontainer/devcontainer.json` lists `"ms-vscode.cpptools"` as an extension to install automatically when the container is created.
- Make a spelling mistake and notice it is detected. The [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) extension was automatically installed because it is referenced in `.devcontainer/devcontainer.json`.
- Also notice that utilities like `Vcpkg` and the [C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension are installed. Tools are installed in the `mcr.microsoft.com/devcontainers/cpp` image and Dev Container settings and metadata are automatically picked up from [image labels](https://containers.dev/implementors/reference/#labels).

Choose a reason for hiding this comment

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

See previous comments on what software should be installed. The current head of the branch removes the C++ extension.

Copy link
Member Author

Choose a reason for hiding this comment

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

To recap:

  1. The second note is highlighting the new image metadata capabilities that brings these extensions across without being in devcontainer.json. See https://containers.dev/implementors/reference/#labels
  2. Happy to have another extension, but this spell checker is present to illustrate that you can supplement image metadata with contents from devcontainer.json.


1. **Terminal:** Press <kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>\`</kbd> and type `uname` and other Linux commands from the terminal window.

1. **Build, Run, and Debug:**
- Open `main.cpp`
- Add a breakpoint (e.g. on line 7).
- Press <kbd>F5</kbd> to launch the app in the container.
- Once the breakpoint is hit, try hovering over variables, examining locals, and more.

1. **Install the GitHub CLI using a Dev Container Feature:**
- Press <kbd>F1</kbd> and select the **Dev Containers: Configure Container Features...** or **Codespaces: Configure Container Features...** command.
- Type "github" in the text box at the top.
- Check check box next to "GitHub CLI" (published by devcontainers)
- Click OK
- Press <kbd>F1</kbd> and select the **Dev Containers: Rebuild Container** or **Codespaces: Rebuild Container** command so the modifications are picked up.

Comment on lines +61 to +67

Choose a reason for hiding this comment

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

This addition prompts an important question for me.

What are the purposes of this repository?

  • To prove to a new-to-dev containers C++ user that the system works for a simple example?
  • To expose C++ to existing dev containers users (providing them an idea of what a functioning C++ project should look like)?
  • To provide a playground to learn about dev container features for someone who just happens to prefer/select the C++ example?

Copy link
Member Author

@Chuxel Chuxel Dec 23, 2022

Choose a reason for hiding this comment

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

The purpose of this repository is to demonstrate the benefits of Dev Containers to C++ users. The sample focuses on things you can do with Dev Containers as a result. Key things to illustrate include:

  1. The extension works in this context just like it does locally
  2. Image metadata capabilities nowallow dev container metadata previously required in devcontainer.json to be directly tied to the image. This avoids "drift" where the image and devcontainer.json get out of sync, enables mass updates, and simplifies devcontainer.json contents at a project level.
  3. How easy it is to add additional capabilities using Dev Container Features

In some cases, extension authors have also opted to illustrate capabilities of the extension (see https://github.com/microsoft/vscode-remote-try-go). Feel free to submit a PR with steps like this if you would like.

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Expand Down