Skip to content

Commit a4f3f03

Browse files
committed
feat(template): add code-server service with Python-ready defaults and CI checks
- add code-server Docker stage with standalone install and extension bootstrap - add code-server service to compose.yaml with env-driven host/port/auth - add .vscode/settings.json.dist and .vscode/extensions.json.dist for Python workflow - include code-server build/smoke check in GitHub CI - document code-server setup and env vars in README - update ignore rules to keep local .vscode/*.json untracked while allowing dist files in build context
1 parent 260d7a5 commit a4f3f03

9 files changed

Lines changed: 123 additions & 7 deletions

File tree

.dockerignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ build/
1515
.env
1616
.DS_Store
1717
.idea/
18-
.vscode/
18+
.vscode/*
19+
!.vscode/settings.json.dist
20+
!.vscode/extensions.json.dist

.env.dist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ DOCKER_PLATFORM=linux/amd64
1111
MIRROR_LIST_COUNTRY=RU
1212
BUILD_PACKAGES="pyenv git gnupg sudo postgresql-libs mariadb-libs openmp"
1313
VIM_PACKAGES="python vim vim-spell-en vim-spell-ru ctags ripgrep bat npm nodejs-lts-jod openai-codex gemini-cli"
14+
CODE_SERVER_EXTENSIONS="ms-python.python ms-pyright.pyright charliermarsh.ruff ms-toolsai.jupyter"
1415

1516
PYTHON_VERSION=3.14
1617
PYTHONUNBUFFERED=1
@@ -20,7 +21,12 @@ POETRY_OPTIONS_APP="--only main --compile"
2021
POETRY_OPTIONS_DEV="--no-root --with dev --compile"
2122
POETRY_NO_INTERACTION=1
2223

24+
CODE_SERVER_HOST=0.0.0.0
25+
CODE_SERVER_PORT=8443
26+
CODE_SERVER_AUTH=password
27+
2328
# Secrets: keep in local .env only; never paste them into logs/issues.
2429
JUPYTER_TOKEN=change_me_to_a_strong_random_token
30+
CODE_SERVER_PASSWORD=change_me_to_a_strong_random_password
2531
OPENAI_API_KEY=
2632
GEMINI_API_KEY=

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
uses: docker/setup-buildx-action@v3
3737

3838
- name: Build images
39-
run: docker compose build dev app vim-ide codex gemini jupyterlab
39+
run: docker compose build dev app vim-ide codex gemini jupyterlab code-server
4040

4141
- name: Check Vim
4242
run: docker compose run --rm -T vim-ide --version
@@ -50,6 +50,9 @@ jobs:
5050
- name: Check JupyterLab
5151
run: docker compose run --rm -T jupyterlab --version
5252

53+
- name: Check code-server
54+
run: docker compose run --rm -T code-server --version
55+
5356
- name: Run app smoke test
5457
run: docker compose run --rm -T app
5558

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
.coc-settings.json
33
.env
44
.vimrc
5+
.vscode/settings.json
6+
.vscode/extensions.json
57

68
# jupyter
79
.ipynb_checkpoints/

.vscode/extensions.json.dist

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"recommendations": [
3+
"ms-python.python",
4+
"ms-pyright.pyright",
5+
"charliermarsh.ruff",
6+
"ms-toolsai.jupyter"
7+
]
8+
}

.vscode/settings.json.dist

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"python.defaultInterpreterPath": "/opt/venv/bin/python",
3+
"python.testing.pytestEnabled": true,
4+
"python.testing.unittestEnabled": false,
5+
"python.testing.pytestArgs": [
6+
"tests"
7+
],
8+
"python.analysis.typeCheckingMode": "basic",
9+
"editor.formatOnSave": true,
10+
"editor.codeActionsOnSave": {
11+
"source.fixAll.ruff": "explicit",
12+
"source.organizeImports.ruff": "explicit"
13+
},
14+
"[python]": {
15+
"editor.defaultFormatter": "charliermarsh.ruff"
16+
},
17+
"ruff.nativeServer": "on",
18+
"ruff.organizeImports": true
19+
}

Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,30 @@ COPY --chown=$DOCKER_USER:$DOCKER_USER .coc-settings.json \
141141
RUN git config --global --add safe.directory /application
142142
ENV TERM=xterm-256color
143143
WORKDIR /application
144+
145+
FROM build-deps-dev AS code-server
146+
ARG DOCKER_HOST_UID=1000
147+
ARG DOCKER_HOST_GID=1000
148+
ARG DOCKER_USER=developer
149+
ARG DOCKER_USER_HOME=/home/developer
150+
ARG CODE_SERVER_EXTENSIONS="ms-python.python ms-pyright.pyright charliermarsh.ruff ms-toolsai.jupyter"
151+
RUN set -eux; \
152+
for attempt in 1 2 3; do \
153+
curl -fsSL https://code-server.dev/install.sh \
154+
| sh -s -- --method standalone --prefix /usr/local \
155+
&& break; \
156+
[ "$attempt" -eq 3 ] && exit 1; \
157+
sleep 5; \
158+
done
159+
RUN /usr/local/bin/code-server --version
160+
RUN mkdir -p $DOCKER_USER_HOME/.local/share/code-server/User && \
161+
chown -R $DOCKER_USER:$DOCKER_USER $DOCKER_USER_HOME/.local/share/code-server
162+
COPY --chown=$DOCKER_USER:$DOCKER_USER .vscode/settings.json.dist \
163+
$DOCKER_USER_HOME/.local/share/code-server/User/settings.json
164+
USER ${DOCKER_HOST_UID}:${DOCKER_HOST_GID}
165+
RUN set -eux; \
166+
for ext in $CODE_SERVER_EXTENSIONS; do \
167+
/usr/local/bin/code-server --install-extension "$ext" --force; \
168+
done
169+
RUN git config --global --add safe.directory /application
170+
WORKDIR /application

README.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* [Optional: Use `dev` for checks and experiments](#optional-use-dev-for-checks-and-experiments)
2424
* [GitHub CI checks](#github-ci-checks)
2525
* [Optional: Run Codex or Gemini (see more examples below)](#optional-run-codex-or-gemini-see-more-examples-below)
26+
* [Optional: Run code-server (VS Code in browser)](#optional-run-code-server-vs-code-in-browser)
2627
* [Optional: Run JupyterLab](#optional-run-jupyterlab)
2728
* [💻 AI-Powered CLI Workflow (Gemini & Codex)](#-ai-powered-cli-workflow-gemini--codex)
2829
* [If you do not have API keys](#if-you-do-not-have-api-keys)
@@ -76,10 +77,12 @@ Use it as-is or tailor it to match your team's development workflow.
7677
```text
7778
.
7879
├── .github/workflows/ci.yml # GitHub CI: build dev/app, run Ruff + pytest
80+
├── .vscode/*.json.dist # VS Code / code-server editor defaults
7981
├── src/sample/main.py # Example application module
8082
├── tests/sample/test_main.py # Example pytest tests to extend in your project
81-
├── Dockerfile # Multi-stage images (base, dev, vim-ide, app)
83+
├── Dockerfile # Multi-stage images (base, dev, vim-ide, code-server, app)
8284
├── compose.yaml # Local service orchestration for template workflows
85+
├── .env.dist # Default compose/build/runtime variables
8386
├── pyproject.toml # Poetry dependencies and tool configuration
8487
├── poetry.lock # Locked dependency graph
8588
└── README.md # Setup and usage documentation
@@ -113,6 +116,8 @@ cp .env.dist .env
113116
cp .vimrc.dist .vimrc
114117
cp .coc-settings.json.dist .coc-settings.json
115118
docker compose build vim-ide
119+
# Optional alternative editor:
120+
# docker compose build code-server
116121
docker compose run --rm vim-ide
117122
```
118123

@@ -144,6 +149,11 @@ Set the `.env` values used by `compose.yaml` and the Docker build. Common ones:
144149
* `POETRY_OPTIONS_DEV` — Poetry install flags for the dev image.
145150
* `PIP_DEFAULT_TIMEOUT` — Pip network timeout (seconds).
146151
* `JUPYTER_TOKEN` — Token for JupyterLab login.
152+
* `CODE_SERVER_EXTENSIONS` — Space-separated extension IDs preinstalled in code-server.
153+
* `CODE_SERVER_HOST` — Bind address for code-server (usually `0.0.0.0`).
154+
* `CODE_SERVER_PORT` — Port for code-server.
155+
* `CODE_SERVER_AUTH` — code-server auth mode (`password` or `none`).
156+
* `CODE_SERVER_PASSWORD` — Password used by code-server when auth is `password`.
147157
* `OPENAI_API_KEY` — API key for Codex.
148158
* `GEMINI_API_KEY` — API key for Gemini.
149159

@@ -189,8 +199,8 @@ docker compose run --rm poetry lock
189199

190200
> 🔄 Note: If you've changed dependencies (e.g. updated pyproject.toml or
191201
> poetry.lock), rebuild the image(s) that install Python dependencies:
192-
> `vim-ide`, `dev`, `codex`, `gemini`, `jupyterlab`, and/or `app` depending on
193-
> what you run.
202+
> `vim-ide`, `dev`, `codex`, `gemini`, `code-server`, `jupyterlab`, and/or
203+
> `app` depending on what you run.
194204
195205
```bash
196206
docker compose build vim-ide
@@ -236,7 +246,8 @@ docker compose run --rm dev ruff format --check
236246
This template includes a minimal GitHub Actions workflow in
237247
`.github/workflows/ci.yml` that:
238248

239-
* builds `dev` and `app` images
249+
* builds `dev`, `app`, `vim-ide`, `codex`, `gemini`, `jupyterlab`, and `code-server`
250+
* checks `vim`, `codex`, `gemini`, `jupyter-lab`, and `code-server` binaries
240251
* runs `ruff check .`
241252
* runs `ruff format --check .`
242253
* runs `pytest -q`
@@ -269,6 +280,25 @@ docker compose build gemini
269280
docker compose run --rm gemini
270281
```
271282

283+
### Optional: Run code-server (VS Code in browser)
284+
285+
Create the editor config files from dist templates (recommended):
286+
287+
```bash
288+
mkdir -p .vscode
289+
cp .vscode/settings.json.dist .vscode/settings.json
290+
cp .vscode/extensions.json.dist .vscode/extensions.json
291+
```
292+
293+
```bash
294+
docker compose build code-server
295+
docker compose run --rm --service-ports code-server
296+
# Open: http://127.0.0.1:${CODE_SERVER_PORT}
297+
```
298+
299+
`compose.yaml` controls port/auth via `CODE_SERVER_HOST`, `CODE_SERVER_PORT`,
300+
`CODE_SERVER_AUTH`, and `CODE_SERVER_PASSWORD`.
301+
272302
### Optional: Run JupyterLab
273303

274304
```bash

compose.yaml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ x-default-args: &default-args
1414
MIRROR_LIST_COUNTRY: ${MIRROR_LIST_COUNTRY:-RU}
1515
BUILD_PACKAGES: ${BUILD_PACKAGES:-pyenv git gnupg sudo postgresql-libs mariadb-libs openmp}
1616
VIM_PACKAGES: ${VIM_PACKAGES:-python vim vim-spell-en vim-spell-ru ctags ripgrep bat npm nodejs-lts-jod openai-codex gemini-cli}
17+
CODE_SERVER_EXTENSIONS: ${CODE_SERVER_EXTENSIONS:-ms-python.python ms-pyright.pyright charliermarsh.ruff ms-toolsai.jupyter}
1718
PYTHON_VERSION: ${PYTHON_VERSION:-3.14}
1819
PIP_DEFAULT_TIMEOUT: ${PIP_DEFAULT_TIMEOUT:-300}
1920
POETRY_VERSION: ${POETRY_VERSION:-2.3.2}
@@ -115,7 +116,25 @@ services:
115116
volumes:
116117
- type: volume
117118
source: codex-auth
118-
target: ${DOCKER_USER_HOME}/.codex
119+
target: ${DOCKER_USER_HOME:-/home/developer}/.codex
120+
code-server:
121+
platform: *platform
122+
<<: *default-shm
123+
entrypoint:
124+
- code-server
125+
- --bind-addr=${CODE_SERVER_HOST:-0.0.0.0}:${CODE_SERVER_PORT:-8443}
126+
- --auth=${CODE_SERVER_AUTH:-password}
127+
- /application
128+
ports:
129+
- "${CODE_SERVER_PORT:-8443}:${CODE_SERVER_PORT:-8443}"
130+
build:
131+
target: code-server
132+
args: *default-args
133+
environment:
134+
<<: *default-env
135+
PASSWORD: ${CODE_SERVER_PASSWORD:-change_me}
136+
volumes:
137+
- *vol-app
119138
jupyterlab:
120139
platform: *platform
121140
<<: *default-shm

0 commit comments

Comments
 (0)