- Dockerfile 52.9%
- Shell 47.1%
|
|
||
|---|---|---|
| .gitea/workflows | ||
| .dockerignore | ||
| .env.sample | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| .setup-precommit.sh | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.es.md | ||
| README.md | ||
🐳 code-server Dev Container with Docker-in-Docker
A developer container powered by code-server, with full Docker CLI support via Docker-in-Docker (DinD). Authentication and user setup is driven by environment variables via .env – ideal for ephemeral, configurable environments.
Features
- 💻 code-server (VS Code in the browser)
- 🐳 Docker-in-Docker (DinD) with fuse-overlayfs storage driver
- 🔐 Dual hashed auth: argon2id for web, yescrypt for doas
- 👤 Dynamic user configuration (UID, GID, password)
- ⚙️ Preinstalled: Docker, AWS CLI v2, kubectl, eksctl, Node.js, Python, Java, pre-commit, etc.
Build
docker build -t code-server-dind .
Environment Configuration (.env)
Create a .env file to define user credentials and container settings:
# === Authentication (required) ===
# Recommended: hashed passwords (no plaintext in .env)
HASHED_PASSWORD=$argon2id$v=19$m=65536,t=3,p=4$...
# Supports yescrypt ($y$), bcrypt ($2a$/$2b$), etc.
DOAS_PASSWORD=$y$j9T$saltsaltsalt$hashhashhash
# Optional fallback (NOT recommended)
# PASSWORD=yourpassword
# === User Configuration ===
DOCKER_USER=coder
UID=1000
GID=1000
# === TimeZone ===
TZ=America/New_York
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
HASHED_PASSWORD |
Yes* | - | Argon2id hash for code-server (web auth) |
DOAS_PASSWORD |
Yes* | - | Hash for doas (terminal auth): yescrypt, bcrypt, etc. |
PASSWORD |
Yes* | - | Plain text fallback (NOT recommended) |
DOCKER_USER |
No | coder |
Username inside the container |
UID |
No | 1000 |
User ID for the container user |
GID |
No | 1000 |
Group ID for the container user |
TZ |
No | UTC |
Timezone (e.g., America/New_York, Europe/Madrid) |
Note
Set
HASHED_PASSWORDandDOAS_PASSWORD(recommended). Or usePASSWORDas a fallback. UsePASSWORD=noneto disable all authentication.
Generating Password Hashes
For HASHED_PASSWORD (code-server) — argon2id
# Using Python (pip install argon2-cffi)
python3 -c "from argon2 import PasswordHasher; print(PasswordHasher().hash('yourpassword'))"
For DOAS_PASSWORD (doas/system) — multiple hash formats
Supported formats: yescrypt ($y$), bcrypt ($2a$/$2b$/$2y$), and others.
Warning
BusyBox
mkpasswd(default in Alpine) only supportsdes,md5,sha256,sha512. Invalid methods likebcryptoryescryptsilently fall back to MD5 — no error. The container usesusermod -pwhich only supports yescrypt and bcrypt-style hashes. Use thewhoispackage version (apt install whois) orpython3instead.
# Yescrypt — mkpasswd from whois package
mkpasswd -m yescrypt yourpassword
# Yescrypt — Python 3
python3 -c "import crypt; print(crypt.crypt('yourpassword', '\$y\$j9T\$'))"
# bcrypt — mkpasswd from whois package
mkpasswd -m bcrypt yourpassword
Run
docker run --rm -it \
--privileged \
-v code-server-home:/home/coder \
--env-file .env \
-p 8080:8080 \
code-server-dind
Volume
All work is persisted in /home/coder, mounted via Docker volume code-server-home.
Authentication Modes
HASHED_PASSWORD=...+DOAS_PASSWORD=<hash>— Recommended. Both hashed. Supported hash types: yescrypt ($y$), bcrypt ($2a$/$2b$/$2y$), and others viausermod -p.HASHED_PASSWORD=...+DOAS_PASSWORD=plain— Hash for web, plain for doas (auto-hashed).HASHED_PASSWORD=...+DOAS_PASSWORD=none— Hash for web, no auth for doas.PASSWORD=yourpass— Fallback. Same plain password for both (NOT recommended).PASSWORD=none— Disables all authentication.
Access
Once running, visit: http://localhost:8080
Login using the credentials defined in .env.
Using Docker
Docker commands require authentication via doas:
docker ps # Prompts for password via alias
doas docker ps # Explicit form
Tooling Included
- Docker CLI (with fuse-overlayfs storage driver for unprivileged containers)
- AWS CLI v2
- kubectl (
v1.33.0) - eksctl
- Node.js + npm
- Python 3 + venv + pipx
- Java Runtime (default-jre)
- pre-commit
- siege, jq, git, etc.
Docker Storage Driver
This container uses fuse-overlayfs as the Docker storage driver, which allows Docker-in-Docker to work efficiently in unprivileged containers without requiring the overlay2 driver. The configuration is automatically set in /etc/docker/daemon.json during container startup.
Resource Limits
The container has resource limits configured in docker-compose.yml to prevent resource exhaustion.
The default values assume a 64 GB RAM / 16+ CPU host. Adjust them according to your system:
deploy:
resources:
limits:
memory: 48G # ~75% of host RAM
cpus: '8.0' # ~50-75% of host CPUs
reservations:
memory: 2G # Minimum guaranteed
cpus: '1.0' # Minimum guaranteed
pids_limit: 1024 # Max processes (for inner containers)
Quick Reference
| Host Specs | Memory Limit | CPU Limit | pids_limit |
|---|---|---|---|
| 16 GB / 4 cores | 12G | 3.0 | 512 |
| 32 GB / 8 cores | 24G | 6.0 | 1024 |
| 64 GB / 16+ cores | 48G | 8.0 | 1024 |
| 128 GB / 32+ cores | 96G | 16.0 | 2048 |
Note
Always leave at least 25% of RAM and some CPU headroom for the host OS.
Security
- 🔒 No
sudo– Removed from container; usesdoasinstead. - 🔑 Dual hashed auth – argon2id for code-server (web), yescrypt for doas (terminal).
- 🔐 Integrity verification – All downloads verified with SHA256/SHA1.
- ⚡ Docker aliases –
docker→doas dockerautomatically (requires auth). - 🛡️ Healthcheck – Automatic service health monitoring.
- 📊 Resource limits – Prevents RAM, CPU, and PID exhaustion.
Clean Up
docker volume rm code-server-home
License
This document is distributed under the terms of the GNU General Public License v3 or later. See the LICENSE file for more details.