Development Containers - the fine print
Development Containers are supposed to liberate your development environment from a specific local installation, like container technology liberated your runtimes (a.k.a YAMLed them into Docker or Kubernetes).
Development != Runtime
Containerization for development has some overlap and quite some difference to containerization for production:
Topic | Development | Production |
---|---|---|
Mutability | You alter container content | Container is static |
Network | Use internal network | Use internal network |
Access | Developer tools++ | Browser / App |
Containers | multiple | multiple |
Volumes | primary container binds projectdir all others mount only |
all: bind or mount |
Configuration | devcontainer.json , docker-compose.yml |
docker-compose.yml ,Helm Chart |
Scope | Runtime & Tooling | Runtime |
Dockerfile | Setup development environment | Configure production |
Insights
- There are many getting started resources available: here, here, here, here and here. They are working examples, commonly strong on what and how, but light on why
- There are plenty of templates to learn by example
- There seem to be substantial differences how it works on different platforms, subtle and annoying
- On macOS (14.4.1) with with the devcontainer plugin 0.364.0 mount binds would not work in auxiliary containers, only in the main app
- I couldn't find any descrption which subset of
docker-compose.yml
is supported - The most interesting templates, for now, live on the Microsoft Artifact Registry, when you know how to look. Starting with those saves you tons of time and frustration
- You will love
code --list-extensions
to figure out the extensions you have in your vscode (unless you are a code n00b and don't have any)
A practical example
You need some kind of Docker, Rancher or Podman Desktop, Visual Studio Code and the Remote Development Extension Pack. You know how to install all this.
Planning
We need to configure the environment, to make it more ~~powerfull~~ confusing, you can add:
- items in the
Dockerfile
- settings in
docker-compose
including.env
files - Container features
- Scripts to run
- VSCode plugins and settings
So we have a few places where e.g. npm install
could live, or tooling.
We will setup a Dockerfile
, a docker-compose.yml
and the devcontainer.json
, all three located in .devcontainer
. Make sure to add this to git, it's kind of the point to share this setup with others, including your future self. Devcontainers are infrastructure as code for developers. So besides your code and servers, you have your tooling and settings in one place. Let's start with the simple one:
Dockerfile
FROM mcr.microsoft.com/devcontainers/javascript-node:dev-20-bookworm
RUN su node -c "npm install -g npm-check-updates nodemon vite"
docker-compose.yml
In the example we have one service (our code)and one NoSQL database.
services:
app:
container_name: nodejs
build:
context: .
dockerfile: Dockerfile
volumes:
- ../..:/workspaces:cached
volumes_from:
- couchdb:rw
command: sleep infinity
network_mode: service:couchdb
depends_on:
- couchdb
couchdb:
image: couchdb:latest
container_name: couchdb
environment:
COUCHDB_USER: admin
COUCHDB_PASSWORD: password
volumes:
- type: volume
source: couchdb_etc
target: /opt/couchdb/etc
- type: volume
source: couchdb_data
target: /opt/couchdb/data
- type: volume
source: couchdb_logs
target: /opt/couchdb/logs
restart: unless-stopped
volumes:
couchdb_data:
couchdb_etc:
couchdb_logs:
- the volume syntax is
../..:/workspaces:cached
to mount the workspace volumes_from
is used to get easy access to the couchDB inin configurationcommand: sleep infinity
is necessary to prevent the container from exitingnetwork_mode
enforces one network setting. To reach it from the outside, you need and entry in devcontainer.json
devcontainer.json
{
"name": "Node.js & couch",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features" : {
"ghcr.io/devcontainers/features/common-utils:2" : {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/sshd:1": {}
},
"postCreateCommand": "yarn install",
"customizations": {
"vscode": {
"extensions": [
"esbenp.prettier-vscode",
"msjsdiag.debugger-for-chrome",
"oderwat.indent-rainbow",
"visualstudioexptteam.vscodeintellicode",
"ritwickdey.liveserver",
"shengchen.vscode-checkstyle",
"sketchbuch.vsc-quokka-statusbar"
"WallabyJs.quokka-vscode",
"WallabyJs.wallaby-vscode"
]
}
},
"forwardPorts": [3000, 5984]
}
In a future post, I'll cover a setup with more than one application / service.
As usual YMMV
Posted by Stephan H Wissel on 12 May 2024 | Comments (0) | categories: Container Docker Java NodeJS WebDevelopment