1+ {
2+ // ============================================================
3+ // WHAT IS A DEV CONTAINER?
4+ // ============================================================
5+ // A Dev Container (devcontainer) lets you define your entire
6+ // development environment as code. VS Code (and GitHub Codespaces)
7+ // reads this file and automatically builds/starts the right
8+ // Docker containers, installs extensions, and configures settings
9+ // — so every team member gets the *exact same* environment.
10+ //
11+ // This project uses the "Docker Compose" variant of dev containers,
12+ // meaning the environment is made up of *multiple* cooperating
13+ // services defined in docker-compose.yml (a multi-container setup).
14+ // ============================================================
15+ // A human-readable label shown in VS Code's title bar / status bar.
16+ "name" : " Ground Control Station — Dev Environment" ,
17+ // ============================================================
18+ // DOCKER COMPOSE FILES
19+ // ============================================================
20+ // Dev containers that use Docker Compose need at least one
21+ // Compose file. Here we list TWO files; Docker Compose merges
22+ // them in order, so the second file can *override or extend*
23+ // values from the first:
24+ //
25+ // 1. ../docker-compose.yml — the production-style base
26+ // Compose file shared with the rest of the project. It defines
27+ // all services (robot-api, backend, frontend) with their images,
28+ // networks, and environment variables.
29+ //
30+ // 2. docker-compose.devcontainer.yml — a dev-only override that
31+ // mounts your local source code *into* the running containers
32+ // (using a bind mount), so edits you make in VS Code are
33+ // immediately visible inside the container without rebuilding.
34+ //
35+ // This "base + override" pattern keeps production config clean
36+ // while adding dev-friendly conveniences only when needed.
37+ "dockerComposeFile" : [
38+ " ../docker-compose.yml" ,
39+ " docker-compose.devcontainer.yml"
40+ ],
41+ // ============================================================
42+ // PRIMARY SERVICE
43+ // ============================================================
44+ // When you have multiple services in your Compose file, VS Code
45+ // needs to know *which one* to "attach" to — i.e., which container
46+ // will be your interactive development shell, run your terminal
47+ // sessions, and host your workspace files.
48+ //
49+ // Here that is "backend" (the FastAPI service you are writing).
50+ // VS Code opens a remote connection directly inside this container.
51+ "service" : " backend" ,
52+ // ============================================================
53+ // WORKSPACE FOLDER
54+ // ============================================================
55+ // The absolute path *inside the container* that VS Code treats as
56+ // the root of your project. The bind mount in
57+ // docker-compose.devcontainer.yml maps your local repo to this
58+ // path, so the files you see in the Explorer are the same files
59+ // the container runs.
60+ "workspaceFolder" : " /workspace" ,
61+ // ============================================================
62+ // ADDITIONAL SERVICES TO START
63+ // ============================================================
64+ // By default VS Code only starts the primary "service" container.
65+ // "runServices" tells it to also start these extra services when
66+ // the dev container opens, so the full stack is available for
67+ // live testing without manual `docker compose up` commands:
68+ //
69+ // • robot-api — a pre-built simulator that mimics a physical
70+ // robot's HTTP API (running on port 5000).
71+ // Your backend talks to this as if it were a
72+ // real robot.
73+ // • frontend — the Nginx web server serving the student UI
74+ // (running on port 80 inside its container).
75+ "runServices" : [
76+ " robot-api" ,
77+ " frontend"
78+ ],
79+ // ============================================================
80+ // PORT FORWARDING
81+ // ============================================================
82+ // Containers run in an isolated Docker network. "forwardPorts"
83+ // creates tunnels so that your *host* machine (and VS Code's
84+ // Simple Browser) can reach ports inside that network.
85+ //
86+ // Format options:
87+ // "service:port" — forward a port from a *named service* container
88+ // number — forward a port from the *primary* service container
89+ //
90+ // • "robot-api:5000" — the simulated robot API (inside robot-api container)
91+ // • 8000 — your FastAPI/uvicorn backend (inside THIS backend devcontainer)
92+ // • "frontend:80" — the Nginx frontend (inside frontend container)
93+ //
94+ // After forwarding, localhost:5000 / localhost:8000 / localhost:80
95+ // on your host all reach the right service.
96+ "forwardPorts" : [
97+ " robot-api:5000" ,
98+ 8000 ,
99+ " frontend:80"
100+ ],
101+ // ============================================================
102+ // PORT LABELS & AUTO-FORWARD BEHAVIOUR
103+ // ============================================================
104+ // "portsAttributes" customises how VS Code handles each forwarded
105+ // port. Two behaviours are configured here:
106+ //
107+ // "notify" — show a toast notification with a link when the
108+ // port becomes available (good for APIs you'll
109+ // call manually or via a REST client).
110+ //
111+ // "openBrowser" — automatically open the system browser when
112+ // the port becomes available (ideal for the UI).
113+ "portsAttributes" : {
114+ "robot-api:5000" : {
115+ "label" : " Robot API (provided)" ,
116+ "onAutoForward" : " notify"
117+ },
118+ "8000" : {
119+ "label" : " Backend API (uvicorn)" ,
120+ "onAutoForward" : " notify"
121+ },
122+ "frontend:80" : {
123+ "label" : " Frontend" ,
124+ // Opens the browser automatically once Nginx is ready.
125+ "onAutoForward" : " openBrowser"
126+ }
127+ },
128+ // ============================================================
129+ // POST-CREATE COMMAND
130+ // ============================================================
131+ // A shell command (or script) that runs *once*, after the
132+ // container is first created and VS Code has connected.
133+ // It does NOT run on subsequent reopens.
134+ //
135+ // Here it simply prints a reminder of how to start the uvicorn
136+ // development server. The server is intentionally NOT started
137+ // automatically so you can make code changes before starting it.
138+ //
139+ // To start the backend, open a terminal in VS Code and run:
140+ // cd /workspace/backend && uvicorn main:app --host 0.0.0.0 --port 8000 --reload
141+ //
142+ // The "--reload" flag makes uvicorn watch for file changes and
143+ // restart automatically — very useful during development.
144+ "postCreateCommand" : " echo 'run \" cd /workspace/backend && uvicorn main:app --host 0.0.0.0 --port 8000 --reload\" to start the backend API'" ,
145+ // ============================================================
146+ // USER ID SYNCHRONISATION
147+ // ============================================================
148+ // On Linux hosts, files created inside the container are owned by
149+ // the container's user UID. If that UID differs from your host
150+ // user's UID, you get permission errors when editing files.
151+ // Setting this to true makes VS Code automatically remap the
152+ // container's user UID to match your host UID — preventing those
153+ // permission issues transparently.
154+ "updateRemoteUserUID" : true ,
155+ // ============================================================
156+ // VS CODE CUSTOMISATIONS
157+ // ============================================================
158+ // "customizations.vscode" lets you declare extensions and editor
159+ // settings that are automatically applied *inside* this dev
160+ // container. This keeps project-specific tooling separate from
161+ // your personal VS Code profile on the host.
162+ "customizations" : {
163+ "vscode" : {
164+ // ----------------------------------------------------------
165+ // EXTENSIONS
166+ // ----------------------------------------------------------
167+ // These extension IDs are installed automatically when the
168+ // dev container starts. Every student gets the same tools
169+ // without having to install anything manually.
170+ //
171+ // ms-python.python — core Python language support
172+ // (run/debug Python files, REPL)
173+ // ms-python.pylance — fast, smart IntelliSense,
174+ // type checking, and auto-imports
175+ // ms-python.black-formatter — code formatter; enforces a
176+ // consistent style automatically
177+ // ms-python.flake8 — linter; highlights style and
178+ // potential bugs as you type
179+ // ms-azuretools.vscode-docker — Docker integration: browse
180+ // containers, images, logs in VS Code
181+ // humao.rest-client — send HTTP requests from .http
182+ // files directly in the editor
183+ // (great for testing your API)
184+ // eamodio.gitlens — enhanced Git history, blame
185+ // annotations, and code authorship
186+ // github.vscode-github-actions — syntax highlighting and
187+ // validation for GitHub Actions
188+ // workflow files (.github/workflows/)
189+ "extensions" : [
190+ " ms-python.python" ,
191+ " ms-python.pylance" ,
192+ " ms-python.black-formatter" ,
193+ " ms-python.flake8" ,
194+ " ms-azuretools.vscode-docker" ,
195+ " humao.rest-client" ,
196+ " eamodio.gitlens" ,
197+ " github.vscode-github-actions"
198+ ],
199+ // ----------------------------------------------------------
200+ // EDITOR SETTINGS
201+ // ----------------------------------------------------------
202+ // These settings override (or add to) VS Code's defaults
203+ // *only* inside this dev container, so they don't affect
204+ // your normal editor setup.
205+ "settings" : {
206+ // Tell the Python extension exactly which interpreter to use.
207+ // This must match the Python installed in the container image
208+ // (set in the Dockerfile / base image).
209+ "python.defaultInterpreterPath" : " /usr/local/bin/python" ,
210+ // Automatically format every file when you save it,
211+ // using whichever formatter is configured for that language.
212+ "editor.formatOnSave" : true ,
213+ // For Python files specifically, use Black as the formatter.
214+ // Black is an opinionated, zero-configuration formatter that
215+ // produces consistent code style across the whole team.
216+ "[python]" : {
217+ "editor.defaultFormatter" : " ms-python.black-formatter"
218+ },
219+ // Enable pytest as the test runner (visible in the Testing
220+ // panel on the VS Code sidebar).
221+ "python.testing.pytestEnabled" : true ,
222+ // Arguments passed to pytest when running tests:
223+ // "tests/" — look for tests in the tests/ subdirectory
224+ // "-v" — verbose output (show each test name)
225+ // "--tb=short" — show a compact traceback on failures
226+ // (easier to read than the full traceback)
227+ "python.testing.pytestArgs" : [
228+ " tests/" ,
229+ " -v" ,
230+ " --tb=short"
231+ ]
232+ }
233+ }
234+ }
235+ }
0 commit comments