Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ce1d0cb

Browse files
matifaliblink-so[bot]
andauthored
Add docker-build template to coder-labs namespace (#235)
This template builds Docker containers from a Dockerfile, rather than using a pre-built image, allowing for more customization of the development environment. Based on the docker template that was removed in coder/coder#15504. --------- Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
1 parent ab87e0e commit ce1d0cb

File tree

3 files changed

+298
-0
lines changed

3 files changed

+298
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
display_name: Docker Build
3+
description: Build Docker containers from Dockerfile as Coder workspaces
4+
icon: ../../../../.icons/docker.svg
5+
verified: true
6+
tags: [docker, container, dockerfile]
7+
---
8+
9+
# Remote Development on Docker Containers (Build from Dockerfile)
10+
11+
Build and provision Docker containers from a Dockerfile as [Coder workspaces](https://coder.com/docs/workspaces) with this example template.
12+
13+
This template builds a custom Docker image from the included Dockerfile, allowing you to customize the development environment by modifying the Dockerfile rather than using a pre-built image.
14+
15+
<!-- TODO: Add screenshot -->
16+
17+
## Prerequisites
18+
19+
### Infrastructure
20+
21+
The VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group:
22+
23+
```sh
24+
# Add coder user to Docker group
25+
sudo adduser coder docker
26+
27+
# Restart Coder server
28+
sudo systemctl restart coder
29+
30+
# Test Docker
31+
sudo -u coder docker ps
32+
```
33+
34+
## Architecture
35+
36+
This template provisions the following resources:
37+
38+
- Docker image (built from Dockerfile and kept locally)
39+
- Docker container pod (ephemeral)
40+
- Docker volume (persistent on `/home/coder`)
41+
42+
This means, when the workspace restarts, any tools or files outside of the home directory are not persisted. To pre-bake tools into the workspace (e.g. `python3`), modify the `build/Dockerfile`. Alternatively, individual developers can [personalize](https://coder.com/docs/dotfiles) their workspaces with dotfiles.
43+
44+
> [!NOTE]
45+
> This template is designed to be a starting point! Edit the Terraform and Dockerfile to extend the template to support your use case.
46+
47+
### Editing the image
48+
49+
Edit the `build/Dockerfile` and run `coder templates push` to update workspaces. The image will be rebuilt automatically when the Dockerfile changes.
50+
51+
## Difference from the standard Docker template
52+
53+
The main difference between this template and the standard Docker template is:
54+
55+
- **Standard Docker template**: Uses a pre-built image (e.g., `codercom/enterprise-base:ubuntu`)
56+
- **Docker Build template**: Builds a custom image from the included `build/Dockerfile`
57+
58+
This allows for more customization of the development environment while maintaining the same workspace functionality.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM ubuntu
2+
3+
RUN apt-get update \
4+
&& apt-get install -y \
5+
curl \
6+
git \
7+
golang \
8+
sudo \
9+
vim \
10+
wget \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
ARG USER=coder
14+
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
15+
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
16+
&& chmod 0440 /etc/sudoers.d/${USER}
17+
USER ${USER}
18+
WORKDIR /home/${USER}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
}
6+
docker = {
7+
source = "kreuzwerker/docker"
8+
}
9+
}
10+
}
11+
12+
locals {
13+
username = data.coder_workspace_owner.me.name
14+
}
15+
16+
variable "docker_socket" {
17+
default = ""
18+
description = "(Optional) Docker socket URI"
19+
type = string
20+
}
21+
22+
provider "docker" {
23+
# Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default
24+
host = var.docker_socket != "" ? var.docker_socket : null
25+
}
26+
27+
data "coder_provisioner" "me" {}
28+
data "coder_workspace" "me" {}
29+
data "coder_workspace_owner" "me" {}
30+
31+
resource "coder_agent" "main" {
32+
arch = data.coder_provisioner.me.arch
33+
os = "linux"
34+
startup_script = <<-EOT
35+
set -e
36+
37+
# Prepare user home with default files on first start.
38+
if [ ! -f ~/.init_done ]; then
39+
cp -rT /etc/skel ~
40+
touch ~/.init_done
41+
fi
42+
43+
# Install the latest code-server.
44+
# Append "--version x.x.x" to install a specific version of code-server.
45+
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
46+
47+
# Start code-server in the background.
48+
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
49+
EOT
50+
51+
# These environment variables allow you to make Git commits right away after creating a
52+
# workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
53+
# You can remove this block if you'd prefer to configure Git manually or using
54+
# dotfiles. (see docs/dotfiles.md)
55+
env = {
56+
GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
57+
GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
58+
GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
59+
GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
60+
}
61+
62+
# The following metadata blocks are optional. They are used to display
63+
# information about your workspace in the dashboard. You can remove them
64+
# if you don't want to display any information.
65+
# For basic resources, you can use the `coder stat` command.
66+
# If you need more control, you can write your own script.
67+
metadata {
68+
display_name = "CPU Usage"
69+
key = "0_cpu_usage"
70+
script = "coder stat cpu"
71+
interval = 10
72+
timeout = 1
73+
}
74+
75+
metadata {
76+
display_name = "RAM Usage"
77+
key = "1_ram_usage"
78+
script = "coder stat mem"
79+
interval = 10
80+
timeout = 1
81+
}
82+
83+
metadata {
84+
display_name = "Home Disk"
85+
key = "3_home_disk"
86+
script = "coder stat disk --path $${HOME}"
87+
interval = 60
88+
timeout = 1
89+
}
90+
91+
metadata {
92+
display_name = "CPU Usage (Host)"
93+
key = "4_cpu_usage_host"
94+
script = "coder stat cpu --host"
95+
interval = 10
96+
timeout = 1
97+
}
98+
99+
metadata {
100+
display_name = "Memory Usage (Host)"
101+
key = "5_mem_usage_host"
102+
script = "coder stat mem --host"
103+
interval = 10
104+
timeout = 1
105+
}
106+
107+
metadata {
108+
display_name = "Load Average (Host)"
109+
key = "6_load_host"
110+
# get load avg scaled by number of cores
111+
script = <<EOT
112+
echo "`cat /proc/loadavg | awk '{ print 1ドル }'` `nproc`" | awk '{ printf "%0.2f", 1ドル/2ドル }'
113+
EOT
114+
interval = 60
115+
timeout = 1
116+
}
117+
118+
metadata {
119+
display_name = "Swap Usage (Host)"
120+
key = "7_swap_host"
121+
script = <<EOT
122+
free -b | awk '/^Swap/ { printf("%.1f/%.1f", 3ドル/1024.0/1024.0/1024.0, 2ドル/1024.0/1024.0/1024.0) }'
123+
EOT
124+
interval = 10
125+
timeout = 1
126+
}
127+
}
128+
129+
resource "coder_app" "code-server" {
130+
agent_id = coder_agent.main.id
131+
slug = "code-server"
132+
display_name = "code-server"
133+
url = "http://localhost:13337/?folder=/home/${local.username}"
134+
icon = "/icon/code.svg"
135+
subdomain = false
136+
share = "owner"
137+
138+
healthcheck {
139+
url = "http://localhost:13337/healthz"
140+
interval = 5
141+
threshold = 6
142+
}
143+
}
144+
145+
resource "docker_volume" "home_volume" {
146+
name = "coder-${data.coder_workspace.me.id}-home"
147+
# Protect the volume from being deleted due to changes in attributes.
148+
lifecycle {
149+
ignore_changes = all
150+
}
151+
# Add labels in Docker to keep track of orphan resources.
152+
labels {
153+
label = "coder.owner"
154+
value = data.coder_workspace_owner.me.name
155+
}
156+
labels {
157+
label = "coder.owner_id"
158+
value = data.coder_workspace_owner.me.id
159+
}
160+
labels {
161+
label = "coder.workspace_id"
162+
value = data.coder_workspace.me.id
163+
}
164+
# This field becomes outdated if the workspace is renamed but can
165+
# be useful for debugging or cleaning out dangling volumes.
166+
labels {
167+
label = "coder.workspace_name_at_creation"
168+
value = data.coder_workspace.me.name
169+
}
170+
}
171+
172+
resource "docker_image" "main" {
173+
name = "coder-${data.coder_workspace.me.id}"
174+
build {
175+
context = "./build"
176+
build_args = {
177+
USER = local.username
178+
}
179+
}
180+
triggers = {
181+
dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
182+
}
183+
}
184+
185+
resource "docker_container" "workspace" {
186+
count = data.coder_workspace.me.start_count
187+
image = docker_image.main.name
188+
# Uses lower() to avoid Docker restriction on container names.
189+
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
190+
# Hostname makes the shell more user friendly: coder@my-workspace:~$
191+
hostname = data.coder_workspace.me.name
192+
# Use the docker gateway if the access URL is 127.0.0.1
193+
entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
194+
env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
195+
host {
196+
host = "host.docker.internal"
197+
ip = "host-gateway"
198+
}
199+
volumes {
200+
container_path = "/home/${local.username}"
201+
volume_name = docker_volume.home_volume.name
202+
read_only = false
203+
}
204+
205+
# Add labels in Docker to keep track of orphan resources.
206+
labels {
207+
label = "coder.owner"
208+
value = data.coder_workspace_owner.me.name
209+
}
210+
labels {
211+
label = "coder.owner_id"
212+
value = data.coder_workspace_owner.me.id
213+
}
214+
labels {
215+
label = "coder.workspace_id"
216+
value = data.coder_workspace.me.id
217+
}
218+
labels {
219+
label = "coder.workspace_name"
220+
value = data.coder_workspace.me.name
221+
}
222+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /