SERVER-110680: Add initial devcontainer setup (#41171)

Co-authored-by: Ivan Fefer <ivan.fefer@mongodb.com>
GitOrigin-RevId: f6ac78093d8fa33d34719d46f7ea08c2442cda4d
This commit is contained in:
Eric Lavigne 2025-09-18 12:10:19 -06:00 committed by MongoDB Bot
parent b4d54e5061
commit 0be3db5ba5
12 changed files with 455 additions and 2 deletions

33
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,33 @@
ARG BASE_IMAGE=quay.io/mongodb/bazel-remote-execution:ubuntu24-2025_09_05-17_18_29
FROM $BASE_IMAGE
ARG BASE_IMAGE
ARG USERNAME=mongo-dev
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user
RUN groupadd $USERNAME && useradd -s /bin/bash --gid $USER_GID -m $USERNAME
RUN apt-get update && apt-get install -y sudo curl
# Give user sudo access
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/devcontaineruser && chmod 0440 /etc/sudoers.d/devcontaineruser
# Persistent bash history
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
&& mkdir /commandhistory \
&& touch /commandhistory/.bash_history \
&& chown -R $USERNAME /commandhistory \
&& echo "$SNIPPET" >> "/home/$USERNAME/.bashrc"
# Toolchain installation
RUN curl -o /toolchain_installer.sh http://mongodbtoolchain.build.10gen.cc/installer.sh && chmod a+x /toolchain_installer.sh
USER $USERNAME
ENV USER ${USERNAME}
RUN /toolchain_installer.sh
# Bazel telemetry
RUN echo "common --bes_keywords=devcontainer:use=true" >> "$HOME/.bazelrc" && \
echo "common --bes_keywords=devcontainer:image=$BASE_IMAGE" >> "$HOME/.bazelrc" && \
echo "common --bes_keywords=devcontainer:username=$USERNAME" >> "$HOME/.bazelrc"

5
.devcontainer/OWNERS.yml Normal file
View File

@ -0,0 +1,5 @@
version: 2.0.0
filters:
- "*":
approvers:
- 10gen/devprod-correctness

View File

@ -0,0 +1,127 @@
{
"name": "MongoDB Development Container",
"build": {
"dockerfile": "./Dockerfile",
"context": "..",
"args": {
"USERNAME": "${localEnv:USER}"
}
},
"mounts": [
{
"source": "engflow_auth",
"target": "/home/${localEnv:USER}/.config/engflow_auth",
"type": "volume"
},
{
"source": "${containerWorkspaceFolderBasename}-cache",
"target": "/home/${localEnv:USER}/.cache",
"type": "volume"
},
{
"source": "projectname-bashhistory",
"target": "/commandhistory",
"type": "volume"
}
],
"containerEnv": {
"HOME": "/home/${localEnv:USER}"
},
"remoteUser": "${localEnv:USER}",
"containerUser": "${localEnv:USER}",
"features": {
"./features/workstation": {},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers-community/features/bazel:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"username": "${localEnv:USER}"
}
},
"postCreateCommand": {
"fixVolumePerms": "sudo chown -R $(whoami): ${containerEnv:HOME}/.config/engflow_auth && sudo chown -R $(whoami): ${containerEnv:HOME}/.cache",
"venvActivation": "echo 'source ${containerWorkspaceFolder}/python3-venv/bin/activate && ${containerWorkspaceFolder}/buildscripts/poetry_sync.sh' >> ~/.bashrc && echo 'source ${containerWorkspaceFolder}/python3-venv/bin/activate && ${containerWorkspaceFolder}/buildscripts/poetry_sync.sh' >> ~/.zshrc;",
"createDataDir": "sudo mkdir -p /data/db && sudo chown -R $(whoami): /data/db"
},
"customizations": {
"vscode": {
"settings": {
"clangd.checkUpdates": true,
"clangd.path": "${workspaceFolder}/buildscripts/clangd_vscode.sh",
"clang-format.executable": "${workspaceRoot}/bazel-out/../../../external/mongo_toolchain_v5/v5/bin/clang-format",
"prettier.prettierPath": "bazel-bin/node_modules/.aspect_rules_js/prettier@3.4.2/node_modules/prettier",
"clang-tidy.executable": "buildscripts/clang_tidy_vscode.py",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript"
],
"files.associations": {
"*.idl": "yaml"
},
"files.insertFinalNewline": true,
"js/ts.implicitProjectConfig.target": "ES2020",
"python.autoComplete.extraPaths": [
"/opt/mongodbtoolchain/v5/share/gcc-14.2.0/python"
],
"python.defaultInterpreterPath": "python3-venv/bin/python",
"python.analysis.extraPaths": [
"/opt/mongodbtoolchain/v5/share/gcc-14.2.0/python"
],
"mypy-type-checker.path": [
"${interpreter}",
"-m",
"mypy"
],
"mypy-type-checker.importStrategy": "fromEnvironment",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[c]": {
"editor.defaultFormatter": "xaver.clang-format",
"editor.formatOnSave": true
},
"[cpp]": {
"editor.defaultFormatter": "xaver.clang-format",
"editor.formatOnSave": true
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[python]": {
"editor.formatOnSaveMode": "file",
"editor.formatOnSave": true,
"editor.defaultFormatter": "charliermarsh.ruff"
},
"[starlark]": {
"editor.defaultFormatter": "BazelBuild.vscode-bazel"
},
"terminal.integrated.wordSeparators": " ()[]{}',\"`─‘’@",
"yaml.schemas": {
"./buildscripts/idl/idl_schema.yml": [
"*.idl"
]
},
"C_Cpp.intelliSenseEngine": "disabled"
},
"extensions": {
"recommendations": [
"llvm-vs-code-extensions.vscode-clangd",
"dbaeumer.vscode-eslint",
"ms-python.python",
"xaver.clang-format",
"cs128.cs128-clang-tidy",
"charliermarsh.ruff",
"ms-python.mypy-type-checker",
"esbenp.prettier-vscode",
"redhat.vscode-yaml",
"streetsidesoftware.code-spell-checker",
"jasonnutter.vscode-codeowners",
"bazelbuild.vscode-bazel",
"rioj7.command-variable",
"augustocdias.tasks-shell-input",
"ms-vscode.cpptools"
]
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"id": "workstation-setup",
"version": "1.0.1",
"name": "Workstation Setup",
"description": "Sets up a development workstation environment with essential tools and configurations.",
"installsAfter": [
"ghcr.io/devcontainers-community/features/bazel"
],
"mounts": [
{
"source": "${containerWorkspaceFolderBasename}-python3-venv",
"target": "${containerWorkspaceFolder}/python3-venv",
"type": "volume"
}
],
"postCreateCommand": "sudo chown -R $(whoami): ${containerWorkspaceFolder}/python3-venv && sudo chown $(whoami): ${containerWorkspaceFolder}/.. && bash /workspace-setup.sh"
}

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
USER=$(_CONTAINER_USER)
cat ./setup.sh >/workspace-setup.sh
sudo chmod a+x /workspace-setup.sh

View File

@ -0,0 +1,173 @@
silent_grep() {
command grep -q "$@" >/dev/null 2>&1
}
idem_file_append() {
if [[ -z "$1" ]]; then
return 1
fi
if [[ ! -f "$1" && -n "${4-}" ]]; then
return
fi
if [[ -z "$2" ]]; then
return 2
fi
if [[ -z "$3" ]]; then
return 3
fi
local start_marker="# BEGIN $2"
local end_marker="# END $2"
if ! silent_grep "^$start_marker" "$1"; then
{
echo -e "\n$start_marker"
echo -e "$3"
echo -e "$end_marker"
} >>"$1"
fi
}
setup_bash() {
# Bash profile should source .bashrc
echo "################################################################################"
echo "Setting up bash..."
local block=$(
cat <<BLOCK
if [[ -f ~/.bashrc ]]; then
source ~/.bashrc
fi
BLOCK
)
idem_file_append ~/.bash_profile "Source .bashrc" "$block"
set +o nounset
source ~/.bash_profile
set -o nounset
echo "Finished setting up ~/.bashprofile..."
}
setup_mongo_venv() {
echo "################################################################################"
echo "Setting up the local virtual environment..."
# PYTHON_KEYRING_BACKEND is needed to make poetry install work
# See guide https://wiki.corp.mongodb.com/display/KERNEL/Virtual+Workstation
export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
/opt/mongodbtoolchain/v4/bin/python3 -m venv python3-venv
source ./python3-venv/bin/activate
POETRY_VIRTUALENVS_IN_PROJECT=true poetry install --no-root --sync
deactivate
echo "Finished setting up the local virtual environment..."
echo "Activate it by running 'source python3-venv/bin/activate'"
}
setup_poetry() {
echo "################################################################################"
echo "Installing 'poetry' command..."
export PATH="$PATH:$HOME/.local/bin"
if command -v poetry &>/dev/null; then
echo "'poetry' command exists; skipping setup"
else
pipx install poetry --pip-args="-r $(pwd)/poetry_requirements.txt"
echo "Finished installing poetry..."
fi
}
setup_pipx() {
echo "################################################################################"
echo "Installing 'pipx' command..."
if command -v pipx &>/dev/null; then
echo "'pipx' command exists; skipping setup"
else
export PATH="$PATH:$HOME/.local/bin"
local venv_name="tmp-pipx-venv"
/opt/mongodbtoolchain/v4/bin/python3 -m venv $venv_name
# virtualenv doesn't like nounset
set +o nounset
source $venv_name/bin/activate
set -o nounset
python -m pip install --upgrade "pip<20.3"
python -m pip install pipx
pipx install pipx --python /opt/mongodbtoolchain/v4/bin/python3 --force
pipx ensurepath --force
set +o nounset
deactivate
set -o nounset
rm -rf $venv_name
source ~/.bashrc
echo "Finished installing pipx..."
fi
}
setup_db_contrib_tool() {
echo "################################################################################"
echo "Installing 'db-contrib-tool' command..."
export PATH="$PATH:$HOME/.local/bin"
if command -v db-contrib-tool &>/dev/null; then
echo "'db-contrib-tool' command exists; skipping setup"
else
pipx install db-contrib-tool
echo "Finished installing db-contrib-tool"
fi
}
setup_clang_config() {
echo "################################################################################"
echo "Installing clang config..."
bazel build compiledb --config=local
echo "Finished installing clang config..."
}
setup_gdb() {
echo "################################################################################"
echo "Setting up GDB..."
cwd=$(pwd)
cd ..
if [[ -d 'Boost-Pretty-Printer' ]]; then
echo "'Boost-Pretty-Printer' dir exists; skipping setup"
else
git clone https://github.com/mongodb-forks/Boost-Pretty-Printer.git
# the original version of this script just appended this line, so we
# have to grep for it manually
if ! silent_grep "source $HOME/gdbinit" ~/.gdbinit; then
idem_file_append ~/.gdbinit "Server Workflow Tool gdbinit" "source $HOME/gdbinit"
fi
echo "Finished installing pretty printers..."
fi
cd $cwd
}
run_setup() {
set +o nounset
source ~/.bashrc
set -o nounset
setup_bash
setup_clang_config
setup_gdb
setup_pipx
setup_db_contrib_tool # This step requires `setup_pipx` to have been run.
setup_poetry # This step requires `setup_pipx` to have been run.
setup_mongo_venv # This step requires `setup_poetry` to have been run.
echo "Please run 'source ~/.bashrc' to complete setup!"
}
run_setup

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
# Ignore everything
*

5
.github/CODEOWNERS vendored
View File

@ -11,6 +11,7 @@ OWNERS.yml @10gen/server-root-ownership @svc-auto-approve-bot
.clang-format @10gen/server-programmability @svc-auto-approve-bot
.clang-tidy.in @10gen/server-programmability @svc-auto-approve-bot
**/.clang-tidy @10gen/server-programmability @svc-auto-approve-bot
.dockerignore @10gen/devprod-correctness @svc-auto-approve-bot
/.editorconfig @10gen/devprod-build @svc-auto-approve-bot
.git* @10gen/devprod-build @svc-auto-approve-bot
.mypy.ini @10gen/devprod-build @10gen/devprod-correctness @svc-auto-approve-bot
@ -29,6 +30,9 @@ sbom.json @10gen/server-security @svc-auto-approve-bot
MODULE.bazel* @10gen/devprod-build @svc-auto-approve-bot
WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
# The following patterns are parsed from ./.devcontainer/OWNERS.yml
/.devcontainer/ @10gen/devprod-correctness @svc-auto-approve-bot
# The following patterns are parsed from ./.github/OWNERS.yml
/.github/ @10gen/server-root-ownership @svc-auto-approve-bot
/.github/ALLOWED_UNOWNED_FILES.yml @svc-auto-approve-bot alex.neben@mongodb.com
@ -292,6 +296,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
# The following patterns are parsed from ./docs/OWNERS.yml
/docs/**/building.md @10gen/devprod-build @svc-auto-approve-bot
/docs/**/cpp_style.md @10gen/server-programmability @svc-auto-approve-bot
/docs/**/devcontainer-setup.md @10gen/devprod-correctness @svc-auto-approve-bot
/docs/**/exception_architecture.md @10gen/server-programmability @svc-auto-approve-bot
/docs/**/golden_data_test_framework.md @10gen/query-optimization @svc-auto-approve-bot
/docs/**/idl.md @10gen/server-programmability @svc-auto-approve-bot

View File

@ -21,6 +21,9 @@ filters:
- "**/.clang-tidy":
approvers:
- 10gen/server-programmability
- ".dockerignore":
approvers:
- 10gen/devprod-correctness
- "/.editorconfig":
approvers:
- 10gen/devprod-build

View File

@ -8,8 +8,11 @@
# bazel run \
# //bazel/remote_execution_container:repin_dockerfiles \
# --config=local
#
# To update the docker images, follow the instructions in the
# confluence page: go/devprod-build-update-rbe-containers.
FROM ubuntu:24.04@sha256:a08e551cb33850e4740772b38217fc1796a66da2506d312abe51acda354ff061
FROM ubuntu:24.04@sha256:9cbed754112939e914291337b5e554b07ad7c392491dba6daf25eef1332a22e8
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@ -21,7 +24,7 @@ RUN apt-get update && \
libncurses-dev=6.4+20240113-1ubuntu2 \
libsasl2-dev=2.1.28+dfsg1-5ubuntu3.1 \
libssl-dev=3.0.13-0ubuntu3.5 \
libxml2-dev=2.9.14+dfsg-1.3ubuntu3.3 \
libxml2-dev=2.9.14+dfsg-1.3ubuntu3.5 \
systemtap-sdt-dev=5.0-2ubuntu1 \
&& rm -rf /var/lib/apt/lists/*

View File

@ -6,6 +6,9 @@ filters:
- "cpp_style.md":
approvers:
- 10gen/server-programmability
- "devcontainer-setup.md":
approvers:
- 10gen/devprod-correctness
- "exception_architecture.md":
approvers:
- 10gen/server-programmability

View File

@ -0,0 +1,76 @@
# MongoDB Development with Devcontainers
**IMPORTANT** The devcontainer setup is currently in the Beta stage
This guide walks you through setting up a MongoDB development environment using devcontainers as the underlying container orchestration tool.
## Prerequisites
### Install Docker
Devcontainers requires Docker to be installed and running on your system, some examples of docker providers are:
- [Rancher Desktop](https://rancherdesktop.io/) (Recommended)
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
- [Orbstack](https://orbstack.dev/)
- [Docker Engine](https://docs.docker.com/engine/install/) (Linux only)
#### Rancher Desktop
If you choose to use Rancher Desktop, you will be prompted to fill in some settings when you first launch the application. You can use the following settings:
- Kubernetes: Choose whatever you like, this isn't required for devcontainers
- Container Engine: `dockerd (moby)`
- Configure Path: "Automatic"
Afterwards, it is recommended to increase the amount of CPU and Memory available to the container engine. You can do this by going to Preferences > Virtual Machine.
## Setup Instructions
### 1. Clone the MongoDB Repository
```bash
git clone https://github.com/mongodb/mongo.git
cd mongo
```
### 2. Install the Remote Containers VSCode Extension
Install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension from the VSCode marketplace.
### 3. Open the clone in VSCode
You may be automatically prompted to open the devcontainer and can confirm. If this does not happen, open the VSCode command palette and enter ">Dev Containers: Reopen in Container".
### 4. Access Your Development Environment
Once setup is complete, VS Code will automatically open with your containerized development environment. You'll have access to:
- **MongoDB source code** mounted in the container
- **Persistent volumes** for caches and configurations
- **Pre-configured VS Code settings** for MongoDB development
- **All development tools** ready to use
## Container Features
### Persistent Storage
The devcontainer uses several persistent volumes to maintain state across container restarts:
- **engflow_auth**: Authentication credentials for EngFlow remote execution
- **python3-venv**: Python virtual environment and dependencies
- **cache**: Build caches and other temporary files
### VS Code Integration
The container includes pre-configured VS Code settings for:
- **C/C++ development** with clangd and clang-format
- **Python development** with ruff and mypy
- **JavaScript development** with ESLint and Prettier
- **Bazel integration** for build system support
- **MongoDB-specific** file associations and schemas
## Additional Resources
- [VS Code Devcontainer Documentation](https://code.visualstudio.com/docs/devcontainers/containers)