mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-11 03:13:16 +00:00
feat(code-server): add code-server from the official codercom image
This commit is contained in:
1 parent
18935e01a7
commit
088579890a
6 files changed
+209
-3
No files matched your search
@@ -105,7 +105,7 @@ directory, one mounted at `/workspace`. The home volume holds settings,
|
||||
credentials and CLI logins; `/workspace` holds the code. Point whatever
|
||||
variable selects the working directory at `/workspace`.
|
||||
|
||||
`code-server-lsio`, `paseo` and `webtop` all follow this. A service with no
|
||||
`code-server`, `code-server-lsio`, `paseo` and `webtop` all follow this. A service with no
|
||||
human inside it does not — an agent such as `hermes` or `openclaw` keeps the
|
||||
volume layout of its official Docker guide.
|
||||
|
||||
@@ -115,7 +115,7 @@ your extensions and logins.
|
||||
|
||||
Check who owns `/workspace` on a fresh volume. Docker creates it `root:root`
|
||||
unless the image ships the directory, and an image that drops to a non-root
|
||||
user will not be able to write there. `code-server-lsio` and `webtop` need an
|
||||
user will not be able to write there. `code-server`, `code-server-lsio` and `webtop` need an
|
||||
explicit `chown` for this reason; `paseo` does not.
|
||||
|
||||
## Environment variable order
|
||||
@@ -201,7 +201,7 @@ Compose interpolation reads the deploying shell's environment before the
|
||||
`.env` file, so a variable must not share a name with anything the shell
|
||||
already exports. `HOSTNAME` is the trap: it is set inside every container,
|
||||
including the one Coolify itself runs in, and would silently win. Hence
|
||||
`SERVICE_HOSTNAME` in `code-server-lsio` and `paseo`.
|
||||
`SERVICE_HOSTNAME` in `code-server`, `code-server-lsio` and `paseo`.
|
||||
|
||||
## Upstream sources
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ Each links to its own README for variables, ports, and storage.
|
||||
| Service | What it is |
|
||||
| --- | --- |
|
||||
| [alloy](alloy/README.md) | Grafana Alloy shipping host and Docker telemetry to Grafana Cloud |
|
||||
| [code-server](code-server/README.md) | VS Code in the browser from the official image |
|
||||
| [code-server-lsio](code-server-lsio/README.md) | VS Code in the browser from the LinuxServer image, as a remote dev box |
|
||||
| [couchbase](couchbase/README.md) | Couchbase Server |
|
||||
| [diun](diun/README.md) | Image-update notifier, reading the Docker API through a read-only proxy |
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copy to .env and fill in. Never commit .env.
|
||||
#
|
||||
# cp .env.example .env
|
||||
|
||||
# Web UI login password. Required.
|
||||
# Generate one with: openssl rand -base64 24
|
||||
PASSWORD=
|
||||
|
||||
# Git identity baked into the container (author + committer).
|
||||
GIT_NAME=
|
||||
GIT_EMAIL=
|
||||
|
||||
# Container hostname, shown in the shell prompt.
|
||||
# Not named HOSTNAME: the deploying shell's own HOSTNAME would override it.
|
||||
SERVICE_HOSTNAME=code-server
|
||||
@@ -0,0 +1,13 @@
|
||||
FROM codercom/code-server:latest
|
||||
|
||||
USER root
|
||||
|
||||
# Extra system packages.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends bubblewrap unzip zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Workspace directory, owned by the container user.
|
||||
RUN mkdir -p /workspace && chown 1000:1000 /workspace
|
||||
|
||||
USER 1000
|
||||
@@ -0,0 +1,157 @@
|
||||
# code-server
|
||||
|
||||
[VS Code in the browser](https://github.com/coder/code-server), from Coder's
|
||||
official `codercom/code-server` image.
|
||||
|
||||
The image ships code-server on Debian with `git`, `zsh`, `curl`, `sudo` and a
|
||||
few editors. The `Dockerfile` adds `bubblewrap`, `zip` and `unzip`. Language
|
||||
toolchains and CLIs are installed into home, below.
|
||||
|
||||
## Toolchains
|
||||
|
||||
Only `/home/coder` and `/workspace` survive a redeploy, so install toolchains
|
||||
and CLIs into home from the editor's terminal. Each command below was tested in
|
||||
the image. Open a new terminal afterwards so the `PATH` changes apply.
|
||||
|
||||
### Official install methods
|
||||
|
||||
These follow the project's own documented install, which already targets home.
|
||||
|
||||
Node.js, with nvm, the method marked recommended for Linux on the
|
||||
[Node.js download page](https://nodejs.org/en/download). nvm, Node and global
|
||||
npm packages all live in `~/.nvm`:
|
||||
|
||||
```sh
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
|
||||
. "$HOME/.nvm/nvm.sh"
|
||||
nvm install 24
|
||||
```
|
||||
|
||||
Python, with uv, from the
|
||||
[uv installation guide](https://docs.astral.sh/uv/getting-started/installation/)
|
||||
and [Python install guide](https://docs.astral.sh/uv/guides/install-python/).
|
||||
uv puts itself in `~/.local/bin` and prebuilt Pythons in
|
||||
`~/.local/share/uv/python`. python.org itself documents only distro packages
|
||||
and source builds, both of which land outside home:
|
||||
|
||||
```sh
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
. "$HOME/.local/bin/env"
|
||||
uv python install 3.13
|
||||
```
|
||||
|
||||
### Suggested by AI, may not be the optimal way
|
||||
|
||||
These use each project's official download, but no official doc covers
|
||||
installing it into home: the location and the latest-version lookup are
|
||||
improvised. Debian's own packages are no alternative, being several releases
|
||||
behind.
|
||||
|
||||
Go, from the official tarball on [go.dev/dl](https://go.dev/dl/).
|
||||
[go.dev/doc/install](https://go.dev/doc/install) extracts it to `/usr/local`;
|
||||
the tarball runs from any directory, so it goes in `~/.local/go`. `go install`
|
||||
puts tools in `~/go/bin`:
|
||||
|
||||
```sh
|
||||
V=$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -1)
|
||||
mkdir -p ~/.local
|
||||
curl -fsSL "https://go.dev/dl/$V.linux-$(dpkg --print-architecture).tar.gz" | tar -C ~/.local -xzf -
|
||||
echo 'export PATH="$HOME/.local/go/bin:$HOME/go/bin:$PATH"' >> ~/.bashrc
|
||||
```
|
||||
|
||||
To upgrade Go, `rm -rf ~/.local/go` and run the same commands again, without
|
||||
the `echo` line.
|
||||
|
||||
Docker CLI, GitHub CLI and GitLab CLI, as the release binaries each project
|
||||
publishes, into `~/.local/bin`:
|
||||
|
||||
- Docker: [static binaries](https://docs.docker.com/engine/install/binaries/),
|
||||
documented for `/usr/bin`. Only the client is taken; the daemon is the
|
||||
host's, through the socket.
|
||||
- GitHub CLI: the `.tar.gz` on [cli.github.com](https://cli.github.com/), with
|
||||
no documented location.
|
||||
- GitLab CLI: the binary from the
|
||||
[releases page](https://gitlab.com/gitlab-org/cli/-/releases), with no
|
||||
documented location.
|
||||
|
||||
```sh
|
||||
mkdir -p ~/.local/bin
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
|
||||
V=$(curl -fsSL https://download.docker.com/linux/static/stable/$(uname -m)/ | grep -o 'docker-[0-9.]*\.tgz' | sort -V | tail -1)
|
||||
curl -fsSL "https://download.docker.com/linux/static/stable/$(uname -m)/$V" | tar -C ~/.local/bin -xzf - --strip-components=1 docker/docker
|
||||
|
||||
V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/cli/cli/releases/latest | sed 's|.*/v||')
|
||||
curl -fsSL "https://github.com/cli/cli/releases/download/v$V/gh_${V}_linux_$ARCH.tar.gz" | tar -C ~/.local/bin -xzf - --strip-components=2 "gh_${V}_linux_$ARCH/bin/gh"
|
||||
|
||||
V=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://gitlab.com/gitlab-org/cli/-/releases/permalink/latest | sed 's|.*/v||')
|
||||
curl -fsSL "https://gitlab.com/gitlab-org/cli/-/releases/v$V/downloads/glab_${V}_linux_$ARCH.tar.gz" | tar -C ~/.local/bin -xzf - --strip-components=1 bin/glab
|
||||
```
|
||||
|
||||
To upgrade one, run the `ARCH=` line and that tool's two lines again; the
|
||||
new binary overwrites the old one.
|
||||
|
||||
## Environment
|
||||
|
||||
| Variable | Purpose |
|
||||
| --- | --- |
|
||||
| `PASSWORD` | Web UI login. Required. |
|
||||
| `GIT_NAME` / `GIT_EMAIL` | Git author and committer identity |
|
||||
| `SERVICE_HOSTNAME` | Container hostname, and the name the shell prompt shows |
|
||||
|
||||
Generate a password with `openssl rand -base64 24`.
|
||||
|
||||
The compose file refuses to start without `PASSWORD`. If it is unset, code-server
|
||||
generates a random password into `~/.config/code-server/config.yaml`, which you
|
||||
can only read from inside the container.
|
||||
|
||||
The `coder` user has passwordless `sudo`, as the image sets it up. Anyone who
|
||||
can log in to the editor is root in the container.
|
||||
|
||||
## Docker access
|
||||
|
||||
The host's Docker socket is bind-mounted at `/var/run/docker.sock`. The image
|
||||
ships no Docker CLI; install the client into home as above. Containers
|
||||
started through it are siblings on the host, not children, so bind mounts in
|
||||
them resolve against host paths.
|
||||
|
||||
The socket belongs to the host's `docker` group, which `coder` is not in.
|
||||
Run it as `sudo ~/.local/bin/docker`: sudo needs no password in this image,
|
||||
but it resets `PATH`, hence the full path. Access to the socket is root on the
|
||||
host, which is accepted here because this is a single-user dev box.
|
||||
|
||||
The `:ro` flag is not a security boundary. It marks the socket file read-only,
|
||||
but clients reach the Docker API by connecting to the socket, which a
|
||||
read-only mount does not stop.
|
||||
|
||||
## Networking
|
||||
|
||||
Listens on `8080`; point the domain at it.
|
||||
|
||||
## Storage
|
||||
|
||||
| Volume | Mount | Holds |
|
||||
| --- | --- | --- |
|
||||
| `code-server-home` | `/home/coder` | Home directory: settings, extensions, shell history, CLI logins |
|
||||
| `code-server-workspace` | `/workspace` | Code you work on |
|
||||
|
||||
The image's entrypoint opens `.`, its working directory. `working_dir:
|
||||
/workspace` makes that the folder code-server opens.
|
||||
|
||||
The `Dockerfile` also makes `/workspace` writable. The image does not
|
||||
ship that directory, so a named volume mounted there comes up `root:root`,
|
||||
and `coder` (uid `1000`) cannot write to it. Creating the directory in the
|
||||
image, owned by `1000:1000`, fixes that without a runtime step, because Docker
|
||||
seeds an empty named volume from the image's directory, ownership included.
|
||||
The home volume needs no such step, because the image already ships
|
||||
`/home/coder` owned by `coder`.
|
||||
|
||||
`bubblewrap`, `zip` and `unzip` are in the `Dockerfile` rather than home
|
||||
because their projects publish no standalone binaries; Debian's packages are
|
||||
the install method, and they land outside home.
|
||||
|
||||
## Image
|
||||
|
||||
`codercom/code-server:latest` is the Debian 13 build and moves with every
|
||||
release. Upstream publishes no major tag.
|
||||
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
code-server:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
hostname: ${SERVICE_HOSTNAME}
|
||||
working_dir: /workspace
|
||||
environment:
|
||||
- PASSWORD=${PASSWORD:?required}
|
||||
- TZ=Asia/Ho_Chi_Minh
|
||||
- GIT_AUTHOR_NAME=${GIT_NAME}
|
||||
- GIT_AUTHOR_EMAIL=${GIT_EMAIL}
|
||||
- GIT_COMMITTER_NAME=${GIT_NAME}
|
||||
- GIT_COMMITTER_EMAIL=${GIT_EMAIL}
|
||||
volumes:
|
||||
- 'code-server-home:/home/coder'
|
||||
- 'code-server-workspace:/workspace'
|
||||
- '/var/run/docker.sock:/var/run/docker.sock:ro'
|
||||
volumes:
|
||||
code-server-home:
|
||||
code-server-workspace:
|
||||
Reference in new issue
Block a user