diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index f93ca90..9ede3db 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,5 +1,4 @@ name: Docker - # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support @@ -9,7 +8,7 @@ on: schedule: - cron: '29 9 * * *' push: - branches: [ "main" ] + branches: [ "main", "1.0.2" ] # Publish semver tags as releases. tags: [ '*.*.*' ] pull_request: @@ -21,10 +20,8 @@ env: # github.repository as / IMAGE_NAME: ${{ github.repository }} - jobs: build: - runs-on: ubuntu-latest permissions: contents: read @@ -37,25 +34,29 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + # Set up QEMU for multi-platform builds + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + # Install the cosign tool except on PR # https://github.com/sigstore/cosign-installer - name: Install cosign if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 + uses: sigstore/cosign-installer@v3.5.0 with: cosign-release: 'v2.2.4' - # Set up BuildKit Docker container builder to be able to build - # multi-platform images and export cache - # https://github.com/docker/setup-buildx-action - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - # Login against a Docker registry except on PR # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -65,7 +66,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} @@ -73,9 +74,10 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@v5 with: context: . + platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} @@ -96,3 +98,4 @@ jobs: # This step uses the identity token to provision an ephemeral certificate # against the sigstore community Fulcio instance. run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} + diff --git a/Dockerfile b/Dockerfile index 6e140b5..277c033 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,51 @@ # Use Debian latest as the base image FROM debian:latest -# Install necessary packages (without software-properties-common as it's no more available in Trixie) -RUN apt-get update && apt-get install -y apt-transport-https wget curl gnupg2 +# Arguments pour la détection de l'architecture +ARG TARGETARCH +ARG TARGETVARIANT -# Add the Microsoft GPG key and repository manually -RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/packages.microsoft.gpg && \ - install -o root -g root -m 644 /tmp/packages.microsoft.gpg /etc/apt/trusted.gpg.d/ && \ - echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \ - rm /tmp/packages.microsoft.gpg - -# Install needed packages on your IDE system -RUN apt-get update && apt-get install -y code - -RUN apt-get -y install sudo -y \ +# Install necessary packages +RUN apt-get update && apt-get install -y \ + apt-transport-https \ + wget \ + curl \ + gnupg2 \ + sudo \ nano \ git \ - curl \ - wget \ unzip \ npm \ - ssh && \ - apt-get clean autoclean && \ + ssh \ + && rm -rf /var/lib/apt/lists/* + +# Install VS Code based on architecture +RUN ARCH=$(dpkg --print-architecture) && \ + echo "Detected architecture: $ARCH (TARGETARCH=$TARGETARCH)" && \ + if [ "$TARGETARCH" = "amd64" ] || [ "$ARCH" = "amd64" ]; then \ + echo "Installing VS Code for amd64..." && \ + wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/packages.microsoft.gpg && \ + install -o root -g root -m 644 /tmp/packages.microsoft.gpg /etc/apt/trusted.gpg.d/ && \ + echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \ + rm /tmp/packages.microsoft.gpg && \ + apt-get update && apt-get install -y code && rm -rf /var/lib/apt/lists/* && \ + echo "VS Code installed successfully" && \ + which code || (echo "ERROR: code command not found after installation!" && exit 1); \ + elif [ "$TARGETARCH" = "arm64" ] || [ "$ARCH" = "arm64" ]; then \ + echo "Installing VS Code for arm64..." && \ + wget https://aka.ms/linux-arm64-deb -O /tmp/vscode-arm64.deb && \ + apt-get update && apt-get install -y /tmp/vscode-arm64.deb && \ + rm /tmp/vscode-arm64.deb && rm -rf /var/lib/apt/lists/* && \ + echo "VS Code installed successfully" && \ + which code || (echo "ERROR: code command not found after installation!" && exit 1); \ + elif [ "$TARGETARCH" = "arm" ] && [ "$TARGETVARIANT" = "v7" ]; then \ + echo "WARNING: VS Code is not officially available for armv7 - container will be built without VS Code"; \ + else \ + echo "WARNING: VS Code is not available for architecture: $TARGETARCH$TARGETVARIANT ($ARCH) - container will be built without VS Code"; \ + fi + +# Additional cleanup +RUN apt-get clean autoclean && \ apt-get autoremove --yes && \ rm -rf /var/lib/{apt,dpkg,cache,log}/ @@ -29,17 +53,17 @@ RUN apt-get -y install sudo -y \ COPY start.sh /app/start.sh RUN chmod +x /app/start.sh -# Create a non-root user -RUN useradd -m vscodeuser && \ +# Create a non-root user with default UID/GID (will be adjustable at runtime via env vars) +RUN groupadd -g 1000 vscodeuser && \ + useradd -m -u 1000 -g 1000 -s /bin/bash vscodeuser && \ echo 'vscodeuser ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/vscodeuser && \ - chmod 0444 /etc/sudoers.d/vscodeuser && \ + chmod 0440 /etc/sudoers.d/vscodeuser && \ usermod -aG sudo vscodeuser -# Switch to the non-root user -USER vscodeuser +# Don't switch to vscodeuser yet - start.sh will handle it # Set the home directory for the non-root user ENV HOME=/home/vscodeuser -# Exécutez le script au lancement du conteneur -ENTRYPOINT ["sh", "/app/start.sh"] \ No newline at end of file +# Exécutez le script au lancement du conteneur (as root to allow UID/GID changes) +ENTRYPOINT ["/app/start.sh"] \ No newline at end of file diff --git a/README.md b/README.md index bb4686f..cf38e28 100644 --- a/README.md +++ b/README.md @@ -1,127 +1,152 @@ -# VS-Code Server - Docker Setup & config +# VS-Code Server - Docker Setup & Config -## Introduction +Official VS Code Server in Docker with WebSocket support, full extension compatibility (including GitHub Copilot), based on Debian. -This repository hosts a Docker setup for deploying an official installation of Visual Studio Code Server using a container. By leveraging the `serve-web` feature of Visual Studio Code, this setup provides an instance of VS Code accessible through a web browser. The base image used is **Debian**, ensuring a light, stable and familiar environment for development. Included in this setup are a Dockerfile and a docker-compose.yml file, simplifying the deployment process. +## Quick Start -**Note:** This setup aims to maintain compatibility with all Visual Studio Code extensions, including those like GitHub Copilot Chat, by using the official version of VS Code Server. It is designed with the intention to support the full range of VS Code features and extensions without the limitations often encountered in non-official installations. +```bash +# Pull and run +docker pull ghcr.io/nerasse/my-code-server:main +docker run -d -p 8585:8585 -e TOKEN=yourtoken ghcr.io/nerasse/my-code-server:main -## Prerequisites +# Or with docker-compose +docker compose up -d +``` -Before you begin, ensure you have the following installed: +Access: `http://localhost:8585?tkn=yourtoken` -- Docker -- Docker Compose (for using the docker-compose.yml) -- Reverse Proxy (for websocket) +## Installation -## Getting Image +### Prerequisites -### Pull image from Docker Package Registry +- Docker +- Docker Compose (optional) +- Reverse Proxy (optional, for production) -To pull the pre-built image from Docker Package Registry, execute the following command: +### Option 1: Using Pre-built Image ```bash docker pull ghcr.io/nerasse/my-code-server:main ``` -### Building the Docker Image - - 1. Clone this repository to your local machine. - 2. Navigate to the directory containing the Dockerfile. - 3. Build the Docker image with the following command: +### Option 2: Build Locally - sudo docker build -t my-code-server:main . +```bash +# Using buildx (recommended) +docker buildx build -t my-code-server:main . -## Running the Container Using Docker Run +# Or using legacy builder +docker build -t my-code-server:main . +``` -If you prefer to use `docker run` instead of Docker Compose, follow these steps: +## Usage - Execute the following command to run the VS Code Server container: +### Docker Compose (Recommended) +**Basic usage:** ```bash - docker run -d -p 8585:8585 -e PORT=8585 -e TOKEN=sometoken my-code-server:main +docker compose up -d ``` -Explanation of flags: - - -d: Run the container in detached mode (in the background). - -p 8585:8585: Map port 8585 of the host to port 8585 of the container (adjust if you changed the default port). - -e PORT=8585: Set the environment variable `PORT` to 8585 (adjust if you changed the default port). - -e TOKEN=sometoken: Set a token for authentication (optional). - -Accessing VS Code Server: - -Once the container is running, you can access the VS Code Server by navigating to: - -```link -http://host:8585?tkn=sometoken +**With custom configuration (.env file):** +```env +HOST_PORT=9090 +CONTAINER_PORT=8585 +TOKEN=mysecuretoken +PUID=1000 +PGID=1000 ``` -host should be replaced with your actual host IP address or domain name. +**With volumes (for persistence):** +Uncomment in `docker-compose.yml`: +```yaml +volumes: + - /path/to/your/data:/home/vscodeuser +``` +### Docker Run -Start using the `docker run` command, along with explanations of the command-line options and additional management commands. +**Basic:** +```bash +docker run -d -p 8585:8585 \ + -e PORT=8585 \ + -e TOKEN=sometoken \ + my-code-server:main +``` -## Starting the VS Code Server with docker compose +**With volumes and custom UID/GID:** +```bash +docker run -d -p 8585:8585 \ + -e PORT=8585 \ + -e TOKEN=sometoken \ + -e PUID=$(id -u) \ + -e PGID=$(id -g) \ + -v /path/to/your/data:/home/vscodeuser \ + my-code-server:main +``` -Use Docker Compose to start the VS Code server: +## Configuration - 1. Navigate to the directory containing the`docker-compose.yml` file. - 2. Run the following command: +### Environment Variables - docker compose up -d +| Variable | Description | Default | +|----------|-------------|---------| +| `PORT` | VS Code Server listening port | `8585` | +| `HOST` | Host interface to listen on | `0.0.0.0` | +| `TOKEN` | Connection token for authentication | None | +| `TOKEN_FILE` | Path to file containing token | - | +| `PUID` | User ID (for volume permissions) | `1000` | +| `PGID` | Group ID (for volume permissions) | `1000` | +| `SERVER_DATA_DIR` | Server data storage directory | - | +| `SERVER_BASE_PATH` | Base path for web UI | - | +| `SOCKET_PATH` | Socket path for server | - | +| `VERBOSE` | Enable verbose output | `false` | +| `LOG_LEVEL` | Log level (trace, debug, info, warn, error, critical, off) | - | +| `CLI_DATA_DIR` | CLI metadata directory | - | - 3. Once the container is running, the VS Code server will be accessible at`http://localhost:8585`. +### Docker Compose Variables -## Configuration +Use environment variables or `.env` file: -- Default port is `8585`. -- Authentication is optional. If not provided, no token will be required. -- To persist data on the host, uncomment the `volumes` section in the `docker-compose.yml` and specify the path. +| Variable | Description | Default | +|----------|-------------|---------| +| `HOST_PORT` | Host port mapping | `8585` | +| `CONTAINER_PORT` | Container port | `8585` | +| `TOKEN` | Authentication token | `sometoken` | +| `PUID` | User ID | `1000` | +| `PGID` | Group ID | `1000` | -## Environment Variables +### Custom UID/GID -The following environment variables can be configured: +To avoid permission issues with mounted volumes, the container supports dynamic UID/GID: -| Variable | Description | Default | -|----------|-------------|---------| -| `PORT` | The port on which VS Code Server will listen | `8585` | -| `HOST` | The host interface to listen on | `0.0.0.0` | -| `TOKEN` | A connection token for authentication | No token if not provided | -| `TOKEN_FILE` | Path to a file containing a connection token | - | -| `SERVER_DATA_DIR` | Directory where server data is stored | - | -| `SERVER_BASE_PATH` | Path under which the web UI and code server is provided | - | -| `SOCKET_PATH` | Socket path for the server to use | - | -| `VERBOSE` | Enable verbose output | `false` | -| `LOG_LEVEL` | Log level (trace, debug, info, warn, error, critical, off) | - | -| `CLI_DATA_DIR` | Directory where CLI metadata should be stored | - | +**With docker-compose:** Set `PUID` and `PGID` environment variables +**With docker run:** Use `-e PUID=$(id -u) -e PGID=$(id -g)` -## Setup: Nginx Reverse Proxy Configuration +The container will automatically adjust user permissions at startup. -To access the VS Code Server (also securely with a domain name and SSL): +## Nginx Reverse Proxy Setup -### Optional Setup: Network Configuration +### Network Configuration -- The container uses the `vscode-server-network` network. -- The container name is `my-code-server`. +- Container name: `my-code-server` +- Network: `vscode-server-network` -### Configuring Nginx HTTP exemple +### HTTP Configuration ```nginx -# my code server server { listen 80; server_name my-code-server.domain.com; location / { - set $codeservervar my-code-server.vscode-server-network:8585; - proxy_pass http://$codeservervar; + proxy_pass http://my-code-server.vscode-server-network:8585; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - # WebSocket support + # WebSocket support (required) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; @@ -129,10 +154,9 @@ server { } ``` -### Configuring Nginx HTTPS/SSL exemple +### HTTPS/SSL Configuration ```nginx -# my code server server { listen 443 ssl; server_name my-code-server.domain.com; @@ -141,14 +165,13 @@ server { ssl_certificate_key /ssl/.domain.com.key; location / { - set $codeservervar my-code-server.vscode-server-network:8585; - proxy_pass http://$codeservervar; + proxy_pass http://my-code-server.vscode-server-network:8585; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - # WebSocket support + # WebSocket support (required) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; @@ -156,17 +179,17 @@ server { } ``` -#### SSL Certificates - -Make sure to have valid SSL certificates for 443 ssl usage. +Access: `https://my-code-server.domain.com?tkn=yourtoken` -### Accessing VS Code Server +## Architecture Support -Access via `https://my-code-server.domain.com` plus `?tkn=sometoken` in the URL if you have set `sometoken` as your token. +- **amd64** (x86_64) - ✅ Fully supported +- **arm64** (aarch64) - ❓ Should work (not tested yet) +- **armv7** - ❌ Not supported -## Security Note +## Security -**Replace all passwords and tokens with secure values. Please be aware of the security implications of using default or published credentials on repositories.** +⚠️ **Important:** Replace default tokens with secure values. Never use published credentials in production. ## Contributing diff --git a/docker-compose.yml b/docker-compose.yml index 2d1acd2..1b1e17b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,13 @@ services: container_name: my-code-server image: ghcr.io/nerasse/my-code-server:main ports: - - "8585:8586" + - "${HOST_PORT:-8585}:${CONTAINER_PORT:-8585}" environment: - - PORT=8586 - - TOKEN=sometoken + - PORT=${CONTAINER_PORT:-8585} + - TOKEN=${TOKEN:-sometoken} + # Uncomment to set custom UID/GID for the vscodeuser (useful for volume permissions) + #- PUID=${PUID:-1000} + #- PGID=${PGID:-1000} #store the data in the host (optional : uncomment the volumes section and change the path) #volumes: # - /home//appdata/my-code-server:/home/vscodeuser/ diff --git a/start.sh b/start.sh index b657581..ef2b9eb 100644 --- a/start.sh +++ b/start.sh @@ -2,6 +2,37 @@ echo "my-code-server debian container" +# Handle UID/GID changes if environment variables are set +if [ -n "$PUID" ] || [ -n "$PGID" ]; then + CURRENT_UID=$(id -u vscodeuser) + CURRENT_GID=$(id -g vscodeuser) + TARGET_UID=${PUID:-$CURRENT_UID} + TARGET_GID=${PGID:-$CURRENT_GID} + + if [ "$CURRENT_UID" != "$TARGET_UID" ] || [ "$CURRENT_GID" != "$TARGET_GID" ]; then + echo "Changing vscodeuser UID:GID from $CURRENT_UID:$CURRENT_GID to $TARGET_UID:$TARGET_GID" + + # Change GID if needed + if [ "$CURRENT_GID" != "$TARGET_GID" ]; then + groupmod -g $TARGET_GID vscodeuser + fi + + # Change UID if needed + if [ "$CURRENT_UID" != "$TARGET_UID" ]; then + usermod -u $TARGET_UID vscodeuser + fi + + # Fix permissions on home directory + chown -R vscodeuser:vscodeuser /home/vscodeuser + + echo "UID/GID changed successfully" + else + echo "Using default UID:GID $CURRENT_UID:$CURRENT_GID" + fi +else + echo "Using default UID:GID $(id -u vscodeuser):$(id -g vscodeuser)" +fi + # Check if PORT environment variable is set, default to 8585 if not if [ -z "$PORT" ]; then echo "No PORT provided, using default port: 8585" @@ -76,6 +107,6 @@ if [ -n "$CLI_DATA_DIR" ]; then CMD="$CMD --cli-data-dir $CLI_DATA_DIR" fi -# Execute the final command -echo "Executing: $CMD" -exec $CMD +# Execute the final command as vscodeuser +echo "Executing: $CMD (as vscodeuser)" +exec su - vscodeuser -c "$CMD"