Development container for the weblog
I set up a development environment for the weblog using a Docker container. The inspiration was the excellent collection of user-friendly containerized applications from linuxserver.io. They even provide complete operating systems with integrated desktop environments, such as Webtop.
One standout container is their code-server, a browser based version of Microsoft VSCode. Since I work on my weblog from different locations, using a code-server based container would allow me to streamline development by eliminating the need to install dependencies on multiple machines.The container should support the full development cycle: retrieving the code from GitHub, editing, debugging in the gui, and pushing updates back to GitHub, which triggers automatic deployment on Cloudflare Pages.
Setting Up the Docker Container
I started by creating a Dockerfile based on the code-server container:
FROM lscr.io/linuxserver/code-server:latest
WORKDIR /config/workspaceI then added a compose.yaml file as per the code-server instructions:
services:
  weblog:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: weblog
	volumes:
      - weblog-data:/config
    environment:
      - PUID=0
      - PGID=0
      - TZ=Europe/Amsterdam
      - DEFAULT_WORKSPACE=/config/workspace
    ports:
      - 8443:8443
    restart: unless-stopped
volumes:
  weblog-data:I used a named volume for the working directory such that it is persistent in between container instances.
Adding Node.js for Astro Framework
Since Astro is a Node.js framework, I needed to install Node.js in the container. I could have used linuxserver.io’s mod system, in particular, the NodeJS mod. However, using a mod would repeat the installation on each startup of the container. I decided to install Node.js during container build time and added the following to the Dockerfile:
ARG NODE_VERSION
# Install Nodejs
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | sudo -E bash - && \
    apt install -y nodejsTo compose.yaml I added:
      args:
        - NODE_VERSION=20Cloning Weblog Code with GitHub CLI
To clone the private weblog GitHub repository, I installed the Github CLI in the container using the following Dockerfile instructions:
RUN (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
	&& sudo mkdir -p -m 755 /etc/apt/keyrings \
	&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
	&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
	&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
	&& sudo apt update \
	&& sudo apt install gh -yTo authenticate with Github, the GH_TOKEN environment variable can be used, or the authentication can be done manually via gh auth login. I added the environment variable to the compose.yaml such that it is copied from the host if it exists and ignored otherwise:
    environment:
      - GH_TOKENThe init.sh script simplifies the setup process and is included in the container
#!/bin/bash
if [ -z "$GH_TOKEN" ]; then
  echo "GH_TOKEN is not set. Authenticating..."
  gh auth login || { echo "Authentication failed."; exit 1; }
else
  echo "GH_TOKEN is set. Skipping manual authentication."
fi
gh repo clone https://[email protected]/XXX/weblog
cd weblog
npm install
npm run astro telemetry disableThe dos2unix utility converts the script to avoid issues with Windows-style line endings:
RUN apt update && \
    apt install -y wget sudo git vim curl unzip dos2unix
COPY init.sh .
RUN dos2unix init.sh && chmod a+x init.shInstalling VSCode Extensions for Astro
To enable Astro support in code-server, I used linuxserver.io’s mod system with the Extension Arguments mod to install the Astro extension inside code-server. I updated compose.yaml with:
    environment:
      - DOCKER_MODS=linuxserver/mods:code-server-extension-arguments
      - VSCODE_EXTENSION_IDS=astro-build.astro-vscodeRunning the Weblog in Development Mode
A port mapping is added in compose.yaml to access the weblog locally from outside the container when run in development mode, :
    ports:
      - 4321:4321By default the weblog running in development mode is only made available on the localhost interface. Hence it is not globally (i.e. outside the container) available. To make the development server listen on all interfaces, I modified the astro.config.mjs file in the Astro project:
export default defineConfig({
  ...
  server: {
    host: true
  },
});Complete Docker and Compose files
Finally, here is the complete Dockerfile:
FROM lscr.io/linuxserver/code-server:latest
WORKDIR /config/workspace
# Install some utilities
RUN apt update && \
    apt install -y wget sudo git vim curl unzip dos2unix
COPY app/* .
# Prepare scripts
RUN dos2unix init.sh && \
    chmod a+x init.sh
ARG NODE_VERSION
# Install Nodejs
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | sudo -E bash - && \
    apt install -y nodejs
# Install Github client
RUN (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
	&& sudo mkdir -p -m 755 /etc/apt/keyrings \
	&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
	&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
	&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
	&& sudo apt update \
	&& sudo apt install gh -yAnd the compose.yaml:
services:
  weblog:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_VERSION=20
    container_name: weblog
    volumes:
      - weblog-data:/config
    environment:
      - DOCKER_MODS=linuxserver/mods:code-server-extension-arguments
      - VSCODE_EXTENSION_IDS=astro-build.astro-vscode
      - GH_TOKEN
      - PUID=0
      - PGID=0
      - TZ=Europe/Amsterdam
      - DEFAULT_WORKSPACE=/config/workspace
    ports:
      - 8443:8443
      - 4321:4321
    restart: unless-stopped
volumes:
  weblog-data: