From 920b2d61da669325183bbd7b099fdd21aaadd810 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 10:06:50 +0000 Subject: [PATCH 01/12] chore(examples/templates): rename `docker-devcontainer` to `docker-envbuilder` --- .../README.md | 14 +++++++------- .../main.tf | 0 2 files changed, 7 insertions(+), 7 deletions(-) rename examples/templates/{docker-devcontainer => docker-envbuilder}/README.md (77%) rename examples/templates/{docker-devcontainer => docker-envbuilder}/main.tf (100%) diff --git a/examples/templates/docker-devcontainer/README.md b/examples/templates/docker-envbuilder/README.md similarity index 77% rename from examples/templates/docker-devcontainer/README.md rename to examples/templates/docker-envbuilder/README.md index 3026a21fc8657..828442d621684 100644 --- a/examples/templates/docker-devcontainer/README.md +++ b/examples/templates/docker-envbuilder/README.md @@ -1,15 +1,15 @@ --- -display_name: Docker (Devcontainer) +display_name: Docker (Envbuilder) description: Provision envbuilder containers as Coder workspaces icon: ../../../site/static/icon/docker.png maintainer_github: coder verified: true -tags: [container, docker, devcontainer] +tags: [container, docker, devcontainer, envbuilder] --- -# Remote Development on Docker Containers (with Devcontainers) +# Remote Development on Docker Containers (with Envbuilder) -Provision Devcontainers as [Coder workspaces](https://coder.com/docs/workspaces) in Docker with this example template. +Provision Envbuilder containers based on `devcontainer.json` as [Coder workspaces](https://coder.com/docs/workspaces) in Docker with this example template. ## Prerequisites @@ -30,7 +30,7 @@ sudo -u coder docker ps ## Architecture -Coder supports Devcontainers via [envbuilder](https://github.com/coder/envbuilder), an open source project. Read more about this in [Coder's documentation](https://coder.com/docs/templates/dev-containers). +Coder supports Envbuilder containers based on `devcontainer.json` via [envbuilder](https://github.com/coder/envbuilder), an open source project. Read more about this in [Coder's documentation](https://coder.com/docs/templates/dev-containers). This template provisions the following resources: @@ -49,7 +49,7 @@ Edit the `devcontainer.json` instead! ## Docker-in-Docker -See the [Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/docker.md) for information on running Docker containers inside a devcontainer built by Envbuilder. +See the [Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/docker.md) for information on running Docker containers inside an Envbuilder container. ## Caching @@ -67,7 +67,7 @@ docker run --detach \ registry:2 ``` -Then, when creating the template, enter `localhost:5000/devcontainer-cache` for the parameter `cache_repo`. +Then, when creating the template, enter `localhost:5000/envbuilder-cache` for the parameter `cache_repo`. See the [Envbuilder Terraform Provider Examples](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf/) for a more complete example of how the provider works. diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-envbuilder/main.tf similarity index 100% rename from examples/templates/docker-devcontainer/main.tf rename to examples/templates/docker-envbuilder/main.tf From cc61effc6d518721e1968fb0817111a7d7661795 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 10:13:13 +0000 Subject: [PATCH 02/12] feat(examples/templates): add docker-devcontainer example template --- .../templates/docker-devcontainer/README.md | 49 +++ .../templates/docker-devcontainer/main.tf | 372 ++++++++++++++++++ 2 files changed, 421 insertions(+) create mode 100644 examples/templates/docker-devcontainer/README.md create mode 100644 examples/templates/docker-devcontainer/main.tf diff --git a/examples/templates/docker-devcontainer/README.md b/examples/templates/docker-devcontainer/README.md new file mode 100644 index 0000000000000..f07ed7f1d0244 --- /dev/null +++ b/examples/templates/docker-devcontainer/README.md @@ -0,0 +1,49 @@ +--- +display_name: Docker-in-Docker Dev Containers +description: Provision Docker containers as Coder workspaces running Dev Containers via Docker-in-Docker. +icon: ../../../site/static/icon/docker.png +maintainer_github: coder +verified: true +tags: [docker, container, devcontainer] +--- + +# Remote Development on Dev Containers + +Provision Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) running [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) via Docker-in-Docker. + + + +## Prerequisites + +### Infrastructure + +The VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group: + +```sh +# Add coder user to Docker group +sudo adduser coder docker + +# Restart Coder server +sudo systemctl restart coder + +# Test Docker +sudo -u coder docker ps +``` + +## Architecture + +This example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It was chosen because it includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool. + +This template provisions the following resources: + +- Docker image (built by Docker socket and kept locally) +- Docker container pod (ephemeral) +- Docker volume (persistent on `/home/coder`) +- Docker volume (persistent on `/var/lib/docker`) + +This means, when the workspace restarts, any tools or files outside of the home directory or docker library are not persisted. + +For devcontainers running inside the workspace, data persistence is dependent on each projects `devcontainer.json` configuration. + +> **Note** +> This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case. diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf new file mode 100644 index 0000000000000..2864d2cd5d943 --- /dev/null +++ b/examples/templates/docker-devcontainer/main.tf @@ -0,0 +1,372 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +locals { + username = data.coder_workspace_owner.me.name + + # Use a workspace image that supports rootless Docker + # (Docker-in-Docker) and Node.js. + workspace_image = "codercom/enterprise-node:ubuntu" +} + +variable "docker_socket" { + default = "" + description = "(Optional) Docker socket URI" + type = string +} + +data "coder_parameter" "repo_url" { + type = "string" + name = "repo_url" + display_name = "Git Repository" + description = "Enter the URL of the Git repository to clone into your workspace. This repository should contain a devcontainer.json file to configure your development environment." + default = "https://github.com/coder/coder" + mutable = true +} + +provider "docker" { + # Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default + host = var.docker_socket != "" ? var.docker_socket : null +} + +data "coder_provisioner" "me" {} +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <<-EOT + set -ex + + # Prepare user home with default files on first start. + if [ ! -f ~/.init_done ]; then + cp -rT /etc/skel ~ + touch ~/.init_done + fi + + if [ "$${CODER_AGENT_URL#*host.docker.internal}" != "$CODER_AGENT_URL" ]; then + # Start the docker service if it is not running, this will create + # the "docker0" interface if it does not exist. + sudo service docker start + + # If the access URL is host.docker.internal, we set up forwarding + # to the host Docker gateway IP address, which is typically + # 172.17.0.1, this will allow the devcontainers to access the + # Coder server even if the access URL has been shadowed by a + # "docker0" interface. This usually happens if docker is started + # inside a devcontainer. + echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward + sudo iptables -t nat -A POSTROUTING -j MASQUERADE + + # Get the IP address of the host Docker gateway, which is + # typically 172.17.0.1 and set up port forwarding between this + # workspace's Docker gateway and the host Docker gateway. + host_ip=$(getent hosts host.docker.internal | awk '{print $1}') + port="$${CODER_AGENT_URL##*:}" + port="$${port%%/*}" + case "$port" in + [0-9]*) + sudo iptables -t nat -A PREROUTING -p tcp --dport $port -j DNAT --to-destination $host_ip:$port + echo "Forwarded port $port to $host_ip" + ;; + *) + sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $host_ip:80 + sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $host_ip:443 + echo "Forwarded default ports 80/443 to $host_ip" + ;; + esac + + # Since we cannot define "--add-host" for devcontainers, we define + # a dnsmasq configuration that allows devcontainers to resolve the + # host.docker.internal URL to this workspace, which is typically + # 172.18.0.1. Note that we take the second IP address from + # "hostname -I" because the first one is usually in the range + # 172.17.0.0/16, which is the host Docker bridge. + dns_ip= + while [ -z "$dns_ip" ]; do + dns_ip=$(hostname -I | awk '{print $2}') + if [ -z "$dns_ip" ]; then + echo "Waiting for hostname -I to return a valid second IP address..." + sleep 1 + fi + done + + # Create a simple dnsmasq configuration to allow devcontainers to + # resolve host.docker.internal. + sudo apt-get update -y + sudo apt-get install -y dnsmasq + + echo "resolv-file=/etc/resolv.conf" | sudo tee /etc/dnsmasq.conf + echo "address=/host.docker.internal/$dns_ip" | sudo tee -a /etc/dnsmasq.conf + echo "no-dhcp-interface=" | sudo tee -a /etc/dnsmasq.conf + echo "bind-interfaces" | sudo tee -a /etc/dnsmasq.conf + echo "listen-address=127.0.0.1,$dns_ip" | sudo tee -a /etc/dnsmasq.conf + + # Restart dnsmasq to apply the new configuration. + sudo service dnsmasq restart + + # Configure Docker to use the dnsmasq server for DNS resolution. + # This allows devcontainers to resolve host.docker.internal to the + # IP address of this workspace. + echo "{\"dns\": [\"$dns_ip\"]}"| sudo tee /etc/docker/daemon.json + + # Restart the Docker service to apply the new configuration. + sudo service docker restart + else + # Start the docker service if it is not running. + sudo service docker start + fi + + # Add any commands that should be executed at workspace startup + # (e.g. install requirements, start a program, etc) here. + EOT + shutdown_script = <<-EOT + set -e + + # Clean up the docker volume from unused resources to keep storage + # usage low. + # + # WARNING! This will remove: + # - all stopped containers + # - all networks not used by at least one container + # - all images without at least one container associated to them + # - all build cache + docker system prune -a -f + + # Stop the Docker service. + sudo service docker stop + EOT + + # These environment variables allow you to make Git commits right away after creating a + # workspace. Note that they take precedence over configuration defined in ~/.gitconfig! + # You can remove this block if you'd prefer to configure Git manually or using + # dotfiles. (see docs/dotfiles.md) + env = { + GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" + GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" + } + + # The following metadata blocks are optional. They are used to display + # information about your workspace in the dashboard. You can remove them + # if you don't want to display any information. + # For basic resources, you can use the `coder stat` command. + # If you need more control, you can write your own script. + metadata { + display_name = "CPU Usage" + key = "0_cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM Usage" + key = "1_ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Home Disk" + key = "3_home_disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } + + metadata { + display_name = "CPU Usage (Host)" + key = "4_cpu_usage_host" + script = "coder stat cpu --host" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Memory Usage (Host)" + key = "5_mem_usage_host" + script = "coder stat mem --host" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Load Average (Host)" + key = "6_load_host" + # get load avg scaled by number of cores + script = < Date: Thu, 3 Jul 2025 10:21:37 +0000 Subject: [PATCH 03/12] fix order --- examples/templates/docker-devcontainer/main.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index 2864d2cd5d943..a0c0f63a23bde 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -54,10 +54,6 @@ resource "coder_agent" "main" { fi if [ "$${CODER_AGENT_URL#*host.docker.internal}" != "$CODER_AGENT_URL" ]; then - # Start the docker service if it is not running, this will create - # the "docker0" interface if it does not exist. - sudo service docker start - # If the access URL is host.docker.internal, we set up forwarding # to the host Docker gateway IP address, which is typically # 172.17.0.1, this will allow the devcontainers to access the @@ -85,6 +81,10 @@ resource "coder_agent" "main" { ;; esac + # Start the docker service if it is not running, this will create + # the "docker0" interface if it does not exist. + sudo service docker start + # Since we cannot define "--add-host" for devcontainers, we define # a dnsmasq configuration that allows devcontainers to resolve the # host.docker.internal URL to this workspace, which is typically From 4b2a928b6122fb3b08e788a307686c5255a6ebd7 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 10:23:10 +0000 Subject: [PATCH 04/12] remove debug output --- examples/templates/docker-devcontainer/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index a0c0f63a23bde..590586d921f82 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -45,7 +45,7 @@ resource "coder_agent" "main" { arch = data.coder_provisioner.me.arch os = "linux" startup_script = <<-EOT - set -ex + set -e # Prepare user home with default files on first start. if [ ! -f ~/.init_done ]; then From 68a298f78e4dd06af49f111be46146083b1d35fa Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 10:24:27 +0000 Subject: [PATCH 05/12] discourage rather than mention possibility --- examples/templates/docker-devcontainer/main.tf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index 590586d921f82..7ae8374612b8f 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -315,12 +315,11 @@ resource "docker_container" "workspace" { image = local.workspace_image # NOTE: The `privileged` mode is one way to run Docker-in-Docker, - # which is required for the devcontainer to work. IF this is not + # which is required for the devcontainer to work. If this is not # desired, you can remove this line. However, you will need to ensure # that the devcontainer can run Docker commands in some other way. - # Mounting the host Docker socket is one way to do this, but it is - # strongly discouraged because workspaces will then compete for - # control of the devcontainers. + # Mounting the host Docker socket is strongly discouraged because + # workspaces will then compete for control of the devcontainers. privileged = true # Uses lower() to avoid Docker restriction on container names. From 314e219a161401071a23dfeeaa63547ae1f75228 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 10:28:48 +0000 Subject: [PATCH 06/12] make gen --- examples/examples.gen.json | 20 +++++++++++++++++--- examples/examples.go | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/examples.gen.json b/examples/examples.gen.json index 8939c0efd30b1..255d6a91f36cc 100644 --- a/examples/examples.gen.json +++ b/examples/examples.gen.json @@ -83,15 +83,29 @@ { "id": "docker-devcontainer", "url": "", - "name": "Docker (Devcontainer)", + "name": "Docker-in-Docker Dev Containers", + "description": "Provision Docker containers as Coder workspaces running Dev Containers via Docker-in-Docker.", + "icon": "/icon/docker.png", + "tags": [ + "docker", + "container", + "devcontainer" + ], + "markdown": "\n# Remote Development on Dev Containers\n\nProvision Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) running [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) via Docker-in-Docker.\n\n\u003c!-- TODO: Add screenshot --\u003e\n\n## Prerequisites\n\n### Infrastructure\n\nThe VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:\n\n```sh\n# Add coder user to Docker group\nsudo adduser coder docker\n\n# Restart Coder server\nsudo systemctl restart coder\n\n# Test Docker\nsudo -u coder docker ps\n```\n\n## Architecture\n\nThis example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It was chosen because it includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool.\n\nThis template provisions the following resources:\n\n- Docker image (built by Docker socket and kept locally)\n- Docker container pod (ephemeral)\n- Docker volume (persistent on `/home/coder`)\n- Docker volume (persistent on `/var/lib/docker`)\n\nThis means, when the workspace restarts, any tools or files outside of the home directory or docker library are not persisted.\n\nFor devcontainers running inside the workspace, data persistence is dependent on each projects `devcontainer.json` configuration.\n\n\u003e **Note**\n\u003e This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.\n" + }, + { + "id": "docker-envbuilder", + "url": "", + "name": "Docker (Envbuilder)", "description": "Provision envbuilder containers as Coder workspaces", "icon": "/icon/docker.png", "tags": [ "container", "docker", - "devcontainer" + "devcontainer", + "envbuilder" ], - "markdown": "\n# Remote Development on Docker Containers (with Devcontainers)\n\nProvision Devcontainers as [Coder workspaces](https://coder.com/docs/workspaces) in Docker with this example template.\n\n## Prerequisites\n\n### Infrastructure\n\nCoder must have access to a running Docker socket, and the `coder` user must be a member of the `docker` group:\n\n```shell\n# Add coder user to Docker group\nsudo usermod -aG docker coder\n\n# Restart Coder server\nsudo systemctl restart coder\n\n# Test Docker\nsudo -u coder docker ps\n```\n\n## Architecture\n\nCoder supports Devcontainers via [envbuilder](https://github.com/coder/envbuilder), an open source project. Read more about this in [Coder's documentation](https://coder.com/docs/templates/dev-containers).\n\nThis template provisions the following resources:\n\n- Envbuilder cached image (conditional, persistent) using [`terraform-provider-envbuilder`](https://github.com/coder/terraform-provider-envbuilder)\n- Docker image (persistent) using [`envbuilder`](https://github.com/coder/envbuilder)\n- Docker container (ephemeral)\n- Docker volume (persistent on `/workspaces`)\n\nThe Git repository is cloned inside the `/workspaces` volume if not present.\nAny local changes to the Devcontainer files inside the volume will be applied when you restart the workspace.\nKeep in mind that any tools or files outside of `/workspaces` or not added as part of the Devcontainer specification are not persisted.\nEdit the `devcontainer.json` instead!\n\n\u003e **Note**\n\u003e This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.\n\n## Docker-in-Docker\n\nSee the [Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/docker.md) for information on running Docker containers inside a devcontainer built by Envbuilder.\n\n## Caching\n\nTo speed up your builds, you can use a container registry as a cache.\nWhen creating the template, set the parameter `cache_repo` to a valid Docker repository.\n\nFor example, you can run a local registry:\n\n```shell\ndocker run --detach \\\n --volume registry-cache:/var/lib/registry \\\n --publish 5000:5000 \\\n --name registry-cache \\\n --net=host \\\n registry:2\n```\n\nThen, when creating the template, enter `localhost:5000/devcontainer-cache` for the parameter `cache_repo`.\n\nSee the [Envbuilder Terraform Provider Examples](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf/) for a more complete example of how the provider works.\n\n\u003e [!NOTE]\n\u003e We recommend using a registry cache with authentication enabled.\n\u003e To allow Envbuilder to authenticate with the registry cache, specify the variable `cache_repo_docker_config_path`\n\u003e with the path to a Docker config `.json` on disk containing valid credentials for the registry.\n" + "markdown": "\n# Remote Development on Docker Containers (with Envbuilder)\n\nProvision Envbuilder containers based on `devcontainer.json` as [Coder workspaces](https://coder.com/docs/workspaces) in Docker with this example template.\n\n## Prerequisites\n\n### Infrastructure\n\nCoder must have access to a running Docker socket, and the `coder` user must be a member of the `docker` group:\n\n```shell\n# Add coder user to Docker group\nsudo usermod -aG docker coder\n\n# Restart Coder server\nsudo systemctl restart coder\n\n# Test Docker\nsudo -u coder docker ps\n```\n\n## Architecture\n\nCoder supports Envbuilder containers based on `devcontainer.json` via [envbuilder](https://github.com/coder/envbuilder), an open source project. Read more about this in [Coder's documentation](https://coder.com/docs/templates/dev-containers).\n\nThis template provisions the following resources:\n\n- Envbuilder cached image (conditional, persistent) using [`terraform-provider-envbuilder`](https://github.com/coder/terraform-provider-envbuilder)\n- Docker image (persistent) using [`envbuilder`](https://github.com/coder/envbuilder)\n- Docker container (ephemeral)\n- Docker volume (persistent on `/workspaces`)\n\nThe Git repository is cloned inside the `/workspaces` volume if not present.\nAny local changes to the Devcontainer files inside the volume will be applied when you restart the workspace.\nKeep in mind that any tools or files outside of `/workspaces` or not added as part of the Devcontainer specification are not persisted.\nEdit the `devcontainer.json` instead!\n\n\u003e **Note**\n\u003e This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.\n\n## Docker-in-Docker\n\nSee the [Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/docker.md) for information on running Docker containers inside an Envbuilder container.\n\n## Caching\n\nTo speed up your builds, you can use a container registry as a cache.\nWhen creating the template, set the parameter `cache_repo` to a valid Docker repository.\n\nFor example, you can run a local registry:\n\n```shell\ndocker run --detach \\\n --volume registry-cache:/var/lib/registry \\\n --publish 5000:5000 \\\n --name registry-cache \\\n --net=host \\\n registry:2\n```\n\nThen, when creating the template, enter `localhost:5000/envbuilder-cache` for the parameter `cache_repo`.\n\nSee the [Envbuilder Terraform Provider Examples](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf/) for a more complete example of how the provider works.\n\n\u003e [!NOTE]\n\u003e We recommend using a registry cache with authentication enabled.\n\u003e To allow Envbuilder to authenticate with the registry cache, specify the variable `cache_repo_docker_config_path`\n\u003e with the path to a Docker config `.json` on disk containing valid credentials for the registry.\n" }, { "id": "gcp-devcontainer", diff --git a/examples/examples.go b/examples/examples.go index 929d6d2bcce04..7deff18f5f9ad 100644 --- a/examples/examples.go +++ b/examples/examples.go @@ -31,6 +31,7 @@ var ( //go:embed templates/digitalocean-linux //go:embed templates/docker //go:embed templates/docker-devcontainer + //go:embed templates/docker-envbuilder //go:embed templates/gcp-devcontainer //go:embed templates/gcp-linux //go:embed templates/gcp-vm-container From e866af2b2f7a2e6b4fbe9d4f11a54e665ef71e7a Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 11:02:41 +0000 Subject: [PATCH 07/12] fix dnsmasq config --- examples/templates/docker-devcontainer/main.tf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index 7ae8374612b8f..1384479d53857 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -105,8 +105,9 @@ resource "coder_agent" "main" { sudo apt-get update -y sudo apt-get install -y dnsmasq - echo "resolv-file=/etc/resolv.conf" | sudo tee /etc/dnsmasq.conf + echo "no-hosts" | sudo tee /etc/dnsmasq.conf echo "address=/host.docker.internal/$dns_ip" | sudo tee -a /etc/dnsmasq.conf + echo "resolv-file=/etc/resolv.conf" | sudo tee -a /etc/dnsmasq.conf echo "no-dhcp-interface=" | sudo tee -a /etc/dnsmasq.conf echo "bind-interfaces" | sudo tee -a /etc/dnsmasq.conf echo "listen-address=127.0.0.1,$dns_ip" | sudo tee -a /etc/dnsmasq.conf From ec80cb0415b045653f0736d5588219d3916e89df Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 11:04:34 +0000 Subject: [PATCH 08/12] copy --- examples/templates/docker-devcontainer/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/templates/docker-devcontainer/README.md b/examples/templates/docker-devcontainer/README.md index f07ed7f1d0244..2b4ac19cc668e 100644 --- a/examples/templates/docker-devcontainer/README.md +++ b/examples/templates/docker-devcontainer/README.md @@ -32,12 +32,12 @@ sudo -u coder docker ps ## Architecture -This example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It was chosen because it includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool. +This example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool. This template provisions the following resources: - Docker image (built by Docker socket and kept locally) -- Docker container pod (ephemeral) +- Docker container (ephemeral) - Docker volume (persistent on `/home/coder`) - Docker volume (persistent on `/var/lib/docker`) From b9a3b721280143e136838ae5f3991d11f0651465 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 11:17:33 +0000 Subject: [PATCH 09/12] move script to coder_script --- .../templates/docker-devcontainer/main.tf | 83 ++----------------- .../scripts/init-docker-in-docker.sh | 83 +++++++++++++++++++ 2 files changed, 92 insertions(+), 74 deletions(-) create mode 100755 examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index 1384479d53857..a02272dab7f7e 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -53,80 +53,6 @@ resource "coder_agent" "main" { touch ~/.init_done fi - if [ "$${CODER_AGENT_URL#*host.docker.internal}" != "$CODER_AGENT_URL" ]; then - # If the access URL is host.docker.internal, we set up forwarding - # to the host Docker gateway IP address, which is typically - # 172.17.0.1, this will allow the devcontainers to access the - # Coder server even if the access URL has been shadowed by a - # "docker0" interface. This usually happens if docker is started - # inside a devcontainer. - echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward - sudo iptables -t nat -A POSTROUTING -j MASQUERADE - - # Get the IP address of the host Docker gateway, which is - # typically 172.17.0.1 and set up port forwarding between this - # workspace's Docker gateway and the host Docker gateway. - host_ip=$(getent hosts host.docker.internal | awk '{print $1}') - port="$${CODER_AGENT_URL##*:}" - port="$${port%%/*}" - case "$port" in - [0-9]*) - sudo iptables -t nat -A PREROUTING -p tcp --dport $port -j DNAT --to-destination $host_ip:$port - echo "Forwarded port $port to $host_ip" - ;; - *) - sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $host_ip:80 - sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $host_ip:443 - echo "Forwarded default ports 80/443 to $host_ip" - ;; - esac - - # Start the docker service if it is not running, this will create - # the "docker0" interface if it does not exist. - sudo service docker start - - # Since we cannot define "--add-host" for devcontainers, we define - # a dnsmasq configuration that allows devcontainers to resolve the - # host.docker.internal URL to this workspace, which is typically - # 172.18.0.1. Note that we take the second IP address from - # "hostname -I" because the first one is usually in the range - # 172.17.0.0/16, which is the host Docker bridge. - dns_ip= - while [ -z "$dns_ip" ]; do - dns_ip=$(hostname -I | awk '{print $2}') - if [ -z "$dns_ip" ]; then - echo "Waiting for hostname -I to return a valid second IP address..." - sleep 1 - fi - done - - # Create a simple dnsmasq configuration to allow devcontainers to - # resolve host.docker.internal. - sudo apt-get update -y - sudo apt-get install -y dnsmasq - - echo "no-hosts" | sudo tee /etc/dnsmasq.conf - echo "address=/host.docker.internal/$dns_ip" | sudo tee -a /etc/dnsmasq.conf - echo "resolv-file=/etc/resolv.conf" | sudo tee -a /etc/dnsmasq.conf - echo "no-dhcp-interface=" | sudo tee -a /etc/dnsmasq.conf - echo "bind-interfaces" | sudo tee -a /etc/dnsmasq.conf - echo "listen-address=127.0.0.1,$dns_ip" | sudo tee -a /etc/dnsmasq.conf - - # Restart dnsmasq to apply the new configuration. - sudo service dnsmasq restart - - # Configure Docker to use the dnsmasq server for DNS resolution. - # This allows devcontainers to resolve host.docker.internal to the - # IP address of this workspace. - echo "{\"dns\": [\"$dns_ip\"]}"| sudo tee /etc/docker/daemon.json - - # Restart the Docker service to apply the new configuration. - sudo service docker restart - else - # Start the docker service if it is not running. - sudo service docker start - fi - # Add any commands that should be executed at workspace startup # (e.g. install requirements, start a program, etc) here. EOT @@ -225,6 +151,15 @@ resource "coder_agent" "main" { } } +resource "coder_script" "init_docker_in_docker" { + count = data.coder_workspace.me.start_count + agent_id = coder_agent.main.id + display_name = "Initialize Docker-in-Docker" + run_on_start = true + icon = "/icon/docker.svg" + script = file("${path.module}/scripts/init-docker-in-docker.sh") +} + # See https://registry.coder.com/modules/coder/devcontainers-cli module "devcontainers-cli" { count = data.coder_workspace.me.start_count diff --git a/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh b/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh new file mode 100755 index 0000000000000..4d36cc1113a5b --- /dev/null +++ b/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh @@ -0,0 +1,83 @@ +#!/bin/sh +set -e + +if [ "${CODER_AGENT_URL#*host.docker.internal}" = "$CODER_AGENT_URL" ]; then + # This is likely an external access URL, so we do not need to set up + # port forwarding or DNS resolution for host.docker.internal. + + # Start the docker service if it is not running. + sudo service docker start + + exit 0 +fi + +# The access URL is host.docker.internal, so we must set up forwarding +# to the host Docker gateway IP address, which is typically 172.17.0.1, +# this will allow the devcontainers to access the Coder server even if +# the access URL has been shadowed by a "docker0" interface. This +# usually happens if docker is started inside a devcontainer. + +# Enable IP forwarding to allow traffic to flow between the host and +# the devcontainers. +echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward +sudo iptables -t nat -A POSTROUTING -j MASQUERADE + +# Get the IP address of the host Docker gateway, which is +# typically 172.17.0.1 and set up port forwarding between this +# workspace's Docker gateway and the host Docker gateway. +host_ip=$(getent hosts host.docker.internal | awk '{print $1}') +port="${CODER_AGENT_URL##*:}" +port="${port%%/*}" +case "$port" in +[0-9]*) + sudo iptables -t nat -A PREROUTING -p tcp --dport $port -j DNAT --to-destination $host_ip:$port + echo "Forwarded port $port to $host_ip" + ;; +*) + sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $host_ip:80 + sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $host_ip:443 + echo "Forwarded default ports 80/443 to $host_ip" + ;; +esac + +# Start the docker service if it is not running, this will create +# the "docker0" interface if it does not exist. +sudo service docker start + +# Since we cannot define "--add-host" for devcontainers, we define +# a dnsmasq configuration that allows devcontainers to resolve the +# host.docker.internal URL to this workspace, which is typically +# 172.18.0.1. Note that we take the second IP address from +# "hostname -I" because the first one is usually in the range +# 172.17.0.0/16, which is the host Docker bridge. +dns_ip= +while [ -z "$dns_ip" ]; do + dns_ip=$(hostname -I | awk '{print $2}') + if [ -z "$dns_ip" ]; then + echo "Waiting for hostname -I to return a valid second IP address..." + sleep 1 + fi +done + +# Create a simple dnsmasq configuration to allow devcontainers to +# resolve host.docker.internal. +sudo apt-get update -y +sudo apt-get install -y dnsmasq + +echo "no-hosts" | sudo tee /etc/dnsmasq.conf +echo "address=/host.docker.internal/$dns_ip" | sudo tee -a /etc/dnsmasq.conf +echo "resolv-file=/etc/resolv.conf" | sudo tee -a /etc/dnsmasq.conf +echo "no-dhcp-interface=" | sudo tee -a /etc/dnsmasq.conf +echo "bind-interfaces" | sudo tee -a /etc/dnsmasq.conf +echo "listen-address=127.0.0.1,$dns_ip" | sudo tee -a /etc/dnsmasq.conf + +# Restart dnsmasq to apply the new configuration. +sudo service dnsmasq restart + +# Configure Docker to use the dnsmasq server for DNS resolution. +# This allows devcontainers to resolve host.docker.internal to the +# IP address of this workspace. +echo "{\"dns\": [\"$dns_ip\"]}" | sudo tee /etc/docker/daemon.json + +# Restart the Docker service to apply the new configuration. +sudo service docker restart From f87b28a3a3190219b0ab0b320990846a6345fe6c Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 11:28:56 +0000 Subject: [PATCH 10/12] make gen --- cli/testdata/coder_templates_init_--help.golden | 2 +- docs/reference/cli/templates_init.md | 6 +++--- examples/examples.gen.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/testdata/coder_templates_init_--help.golden b/cli/testdata/coder_templates_init_--help.golden index 4d3cd1c2a1228..d44db24aee27b 100644 --- a/cli/testdata/coder_templates_init_--help.golden +++ b/cli/testdata/coder_templates_init_--help.golden @@ -6,7 +6,7 @@ USAGE: Get started with a templated template. OPTIONS: - --id aws-devcontainer|aws-linux|aws-windows|azure-linux|digitalocean-linux|docker|docker-devcontainer|gcp-devcontainer|gcp-linux|gcp-vm-container|gcp-windows|kubernetes|kubernetes-devcontainer|nomad-docker|scratch + --id aws-devcontainer|aws-linux|aws-windows|azure-linux|digitalocean-linux|docker|docker-devcontainer|docker-envbuilder|gcp-devcontainer|gcp-linux|gcp-vm-container|gcp-windows|kubernetes|kubernetes-devcontainer|nomad-docker|scratch Specify a given example template by ID. ——— diff --git a/docs/reference/cli/templates_init.md b/docs/reference/cli/templates_init.md index 30df7bb9c0ad3..7613144e66018 100644 --- a/docs/reference/cli/templates_init.md +++ b/docs/reference/cli/templates_init.md @@ -13,8 +13,8 @@ coder templates init [flags] [directory] ### --id -| | | -|------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Type | aws-devcontainer\|aws-linux\|aws-windows\|azure-linux\|digitalocean-linux\|docker\|docker-devcontainer\|gcp-devcontainer\|gcp-linux\|gcp-vm-container\|gcp-windows\|kubernetes\|kubernetes-devcontainer\|nomad-docker\|scratch | +| | | +|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Type | aws-devcontainer\|aws-linux\|aws-windows\|azure-linux\|digitalocean-linux\|docker\|docker-devcontainer\|docker-envbuilder\|gcp-devcontainer\|gcp-linux\|gcp-vm-container\|gcp-windows\|kubernetes\|kubernetes-devcontainer\|nomad-docker\|scratch | Specify a given example template by ID. diff --git a/examples/examples.gen.json b/examples/examples.gen.json index 255d6a91f36cc..c891389568a55 100644 --- a/examples/examples.gen.json +++ b/examples/examples.gen.json @@ -91,7 +91,7 @@ "container", "devcontainer" ], - "markdown": "\n# Remote Development on Dev Containers\n\nProvision Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) running [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) via Docker-in-Docker.\n\n\u003c!-- TODO: Add screenshot --\u003e\n\n## Prerequisites\n\n### Infrastructure\n\nThe VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:\n\n```sh\n# Add coder user to Docker group\nsudo adduser coder docker\n\n# Restart Coder server\nsudo systemctl restart coder\n\n# Test Docker\nsudo -u coder docker ps\n```\n\n## Architecture\n\nThis example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It was chosen because it includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool.\n\nThis template provisions the following resources:\n\n- Docker image (built by Docker socket and kept locally)\n- Docker container pod (ephemeral)\n- Docker volume (persistent on `/home/coder`)\n- Docker volume (persistent on `/var/lib/docker`)\n\nThis means, when the workspace restarts, any tools or files outside of the home directory or docker library are not persisted.\n\nFor devcontainers running inside the workspace, data persistence is dependent on each projects `devcontainer.json` configuration.\n\n\u003e **Note**\n\u003e This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.\n" + "markdown": "\n# Remote Development on Dev Containers\n\nProvision Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) running [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) via Docker-in-Docker.\n\n\u003c!-- TODO: Add screenshot --\u003e\n\n## Prerequisites\n\n### Infrastructure\n\nThe VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:\n\n```sh\n# Add coder user to Docker group\nsudo adduser coder docker\n\n# Restart Coder server\nsudo systemctl restart coder\n\n# Test Docker\nsudo -u coder docker ps\n```\n\n## Architecture\n\nThis example uses the `codercom/enterprise-node:ubuntu` Docker image as a base image for the workspace. It includes necessary tools like Docker and Node.js, which are required for running Dev Containers via the `@devcontainers/cli` tool.\n\nThis template provisions the following resources:\n\n- Docker image (built by Docker socket and kept locally)\n- Docker container (ephemeral)\n- Docker volume (persistent on `/home/coder`)\n- Docker volume (persistent on `/var/lib/docker`)\n\nThis means, when the workspace restarts, any tools or files outside of the home directory or docker library are not persisted.\n\nFor devcontainers running inside the workspace, data persistence is dependent on each projects `devcontainer.json` configuration.\n\n\u003e **Note**\n\u003e This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case.\n" }, { "id": "docker-envbuilder", From ab40359db6c9a7115eb9c5d7953cd5c1692b2c55 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 11:35:55 +0000 Subject: [PATCH 11/12] rewrite comments --- .../scripts/init-docker-in-docker.sh | 86 +++++++++++-------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh b/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh index 4d36cc1113a5b..57022d22a47b4 100755 --- a/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh +++ b/examples/templates/docker-devcontainer/scripts/init-docker-in-docker.sh @@ -1,55 +1,69 @@ #!/bin/sh set -e -if [ "${CODER_AGENT_URL#*host.docker.internal}" = "$CODER_AGENT_URL" ]; then - # This is likely an external access URL, so we do not need to set up - # port forwarding or DNS resolution for host.docker.internal. +# Docker-in-Docker setup for Coder dev containers using host.docker.internal +# URLs. When Docker runs inside a container, the "docker0" bridge interface +# can interfere with host.docker.internal DNS resolution, breaking +# connectivity to the Coder server. - # Start the docker service if it is not running. +if [ "${CODER_AGENT_URL#*host.docker.internal}" = "$CODER_AGENT_URL" ]; then + # External access URL detected, no networking workarounds needed. sudo service docker start - exit 0 fi -# The access URL is host.docker.internal, so we must set up forwarding -# to the host Docker gateway IP address, which is typically 172.17.0.1, -# this will allow the devcontainers to access the Coder server even if -# the access URL has been shadowed by a "docker0" interface. This -# usually happens if docker is started inside a devcontainer. +# host.docker.internal URL detected. Docker's default bridge network creates +# a "docker0" interface that can shadow the host.docker.internal hostname +# resolution. This typically happens when Docker starts inside a devcontainer, +# as the inner Docker daemon creates its own bridge network that conflicts +# with the outer one. -# Enable IP forwarding to allow traffic to flow between the host and -# the devcontainers. +# Enable IP forwarding to allow packets to route between the host network and +# the devcontainer networks. Without this, traffic cannot flow properly +# between the different Docker bridge networks. echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward sudo iptables -t nat -A POSTROUTING -j MASQUERADE -# Get the IP address of the host Docker gateway, which is -# typically 172.17.0.1 and set up port forwarding between this -# workspace's Docker gateway and the host Docker gateway. +# Set up port forwarding to the host Docker gateway (typically 172.17.0.1). +# We resolve host.docker.internal to get the actual IP and create NAT rules +# to forward traffic from this workspace to the host. host_ip=$(getent hosts host.docker.internal | awk '{print $1}') + +echo "Host IP for host.docker.internal: $host_ip" + +# Extract the port from CODER_AGENT_URL. The URL format is typically +# http://host.docker.internal:port/. port="${CODER_AGENT_URL##*:}" port="${port%%/*}" case "$port" in [0-9]*) - sudo iptables -t nat -A PREROUTING -p tcp --dport $port -j DNAT --to-destination $host_ip:$port + # Specific port found, forward it to the host gateway. + sudo iptables -t nat -A PREROUTING -p tcp --dport "$port" -j DNAT --to-destination "$host_ip:$port" echo "Forwarded port $port to $host_ip" ;; *) - sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $host_ip:80 - sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $host_ip:443 + # No specific port or non-numeric port, forward standard web ports. + sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination "$host_ip:80" + sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination "$host_ip:443" echo "Forwarded default ports 80/443 to $host_ip" ;; esac -# Start the docker service if it is not running, this will create -# the "docker0" interface if it does not exist. +# Start Docker service, which creates the "docker0" interface if it doesn't +# exist. We need the interface to extract the second IP address for DNS +# resolution. sudo service docker start -# Since we cannot define "--add-host" for devcontainers, we define -# a dnsmasq configuration that allows devcontainers to resolve the -# host.docker.internal URL to this workspace, which is typically -# 172.18.0.1. Note that we take the second IP address from -# "hostname -I" because the first one is usually in the range -# 172.17.0.0/16, which is the host Docker bridge. +# Configure DNS resolution to avoid requiring devcontainer project modifications. +# While devcontainers can use the "--add-host" flag, it requires explicit +# definition in devcontainer.json. Using a DNS server instead means every +# devcontainer project doesn't need to accommodate this. + +# Wait for the workspace to acquire its Docker bridge IP address. The +# "hostname -I" command returns multiple IPs: the first is typically the host +# Docker bridge (172.17.0.0/16 range) and the second is the workspace Docker +# bridge (172.18.0.0/16). We need the second IP because that's where +# devcontainers will be able to reach us. dns_ip= while [ -z "$dns_ip" ]; do dns_ip=$(hostname -I | awk '{print $2}') @@ -59,11 +73,17 @@ while [ -z "$dns_ip" ]; do fi done -# Create a simple dnsmasq configuration to allow devcontainers to -# resolve host.docker.internal. +echo "Using DNS IP: $dns_ip" + +# Install dnsmasq to provide custom DNS resolution. This lightweight DNS +# server allows us to override specific hostname lookups without affecting +# other DNS queries. sudo apt-get update -y sudo apt-get install -y dnsmasq +# Configure dnsmasq to resolve host.docker.internal to this workspace's IP. +# This ensures devcontainers can find the Coder server even when the "docker0" +# interface would normally shadow the hostname resolution. echo "no-hosts" | sudo tee /etc/dnsmasq.conf echo "address=/host.docker.internal/$dns_ip" | sudo tee -a /etc/dnsmasq.conf echo "resolv-file=/etc/resolv.conf" | sudo tee -a /etc/dnsmasq.conf @@ -71,13 +91,11 @@ echo "no-dhcp-interface=" | sudo tee -a /etc/dnsmasq.conf echo "bind-interfaces" | sudo tee -a /etc/dnsmasq.conf echo "listen-address=127.0.0.1,$dns_ip" | sudo tee -a /etc/dnsmasq.conf -# Restart dnsmasq to apply the new configuration. sudo service dnsmasq restart -# Configure Docker to use the dnsmasq server for DNS resolution. -# This allows devcontainers to resolve host.docker.internal to the -# IP address of this workspace. +# Configure Docker daemon to use our custom DNS server. This is the critical +# piece that ensures all containers (including devcontainers) use our dnsmasq +# server for hostname resolution, allowing them to properly resolve +# host.docker.internal. echo "{\"dns\": [\"$dns_ip\"]}" | sudo tee /etc/docker/daemon.json - -# Restart the Docker service to apply the new configuration. sudo service docker restart From ecb35dbecff7a9bdbf8962b66fafe08553a3aa63 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 3 Jul 2025 12:28:45 +0000 Subject: [PATCH 12/12] revirew: mention docks --- examples/templates/docker-devcontainer/main.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/templates/docker-devcontainer/main.tf b/examples/templates/docker-devcontainer/main.tf index a02272dab7f7e..a0275067a57e7 100644 --- a/examples/templates/docker-devcontainer/main.tf +++ b/examples/templates/docker-devcontainer/main.tf @@ -256,6 +256,8 @@ resource "docker_container" "workspace" { # that the devcontainer can run Docker commands in some other way. # Mounting the host Docker socket is strongly discouraged because # workspaces will then compete for control of the devcontainers. + # For more information, see: + # https://coder.com/docs/admin/templates/extending-templates/docker-in-workspaces privileged = true # Uses lower() to avoid Docker restriction on container names.