docs: update template-from-scratch (#15101)
closes https://github.com/coder/internal/issues/104 - [x] update screenshots - [x] consistent md - [x] confirm and update `Dockerfile` and `main.tf` - matched up to the Docker Containers starter template - upload template - [x] confirm CLI steps - [x] add steps in tab for Dashboard - [x] ~confirm that the expand works~ it doesn't <https://coder.com/docs/@template-from-scratch-update/tutorials/template-from-scratch> --------- Co-authored-by: EdwardAngert <17991901+EdwardAngert@users.noreply.github.com>
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 497 KiB After Width: | Height: | Size: 66 KiB |
@@ -1,30 +1,15 @@
|
||||
# A guided tour of a template
|
||||
# Write a template from scratch
|
||||
|
||||
This guided tour introduces you to the different parts of a Coder template by
|
||||
showing you how to create a template from scratch.
|
||||
A template is a common configuration that you use to deploy workspaces.
|
||||
|
||||
You'll write a simple template that provisions a workspace as a Docker container
|
||||
with Ubuntu.
|
||||
This tutorial teaches you how to create a template that provisions a workspace
|
||||
as a Docker container with Ubuntu.
|
||||
|
||||
## Before you start
|
||||
|
||||
To follow this guide, you'll need:
|
||||
|
||||
- A computer or cloud computing instance with both
|
||||
[Docker](https://docs.docker.com/get-docker/) and [Coder](../install/index.md)
|
||||
installed on it.
|
||||
|
||||
> When setting up your computer or computing instance, make sure to install
|
||||
> Docker first, then Coder. Otherwise, you'll need to add the `coder` user to
|
||||
> the `docker` group.
|
||||
|
||||
- The URL for your Coder instance. If you're running Coder locally, the default
|
||||
URL is [http://127.0.0.1:3000](http://127.0.0.1:3000).
|
||||
|
||||
- A text editor. For this tour, we use [GNU nano](https://nano-editor.org/).
|
||||
|
||||
> Haven't written Terraform before? Check out Hashicorp's
|
||||
> [Getting Started Guides](https://developer.hashicorp.com/terraform/tutorials).
|
||||
You'll need a computer or cloud computing instance with both
|
||||
[Docker](https://docs.docker.com/get-docker/) and [Coder](../install/index.md)
|
||||
installed on it.
|
||||
|
||||
## What's in a template
|
||||
|
||||
@@ -36,25 +21,25 @@ Coder can provision all Terraform modules, resources, and properties. The Coder
|
||||
server essentially runs a `terraform apply` every time a workspace is created,
|
||||
started, or stopped.
|
||||
|
||||
> Haven't written Terraform before? Check out Hashicorp's
|
||||
> [Getting Started Guides](https://developer.hashicorp.com/terraform/tutorials).
|
||||
|
||||
Here's a simplified diagram that shows the main parts of the template we'll
|
||||
create.
|
||||
create:
|
||||
|
||||

|
||||
|
||||
## 1. Create template files
|
||||
|
||||
On your local computer, create a directory for your template and create the
|
||||
`Dockerfile`.
|
||||
`Dockerfile`. You will upload the files to your Coder instance later.
|
||||
|
||||
```sh
|
||||
mkdir template-tour
|
||||
cd template-tour
|
||||
mkdir build
|
||||
nano build/Dockerfile
|
||||
mkdir -p template-tour/build && cd $_
|
||||
```
|
||||
|
||||
You'll enter a simple `Dockerfile` that starts with the
|
||||
[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In the editor, enter
|
||||
Enter content into a `Dockerfile` that starts with the
|
||||
[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In your editor, enter
|
||||
and save the following text in `Dockerfile` then exit the editor:
|
||||
|
||||
```dockerfile
|
||||
@@ -72,56 +57,48 @@ RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
|
||||
&& chmod 0440 /etc/sudoers.d/${USER}
|
||||
USER ${USER}
|
||||
WORKDIR /home/${USER}
|
||||
|
||||
```
|
||||
|
||||
Notice how `Dockerfile` adds a few things to the parent `ubuntu` image, which
|
||||
your template needs later:
|
||||
`Dockerfile` adds a few things to the parent `ubuntu` image, which your template
|
||||
needs later:
|
||||
|
||||
- It installs the `sudo` and `curl` packages.
|
||||
- It adds a `coder` user, including a home directory.
|
||||
|
||||
## 2. Set up template providers
|
||||
|
||||
Now you can edit the Terraform file, which provisions the workspace's resources.
|
||||
Edit the Terraform `main.tf` file to provision the workspace's resources.
|
||||
|
||||
```shell
|
||||
nano main.tf
|
||||
```
|
||||
|
||||
We'll start by setting up our providers. At a minimum, we need the `coder`
|
||||
provider. For this template, we also need the `docker` provider:
|
||||
Start by setting up the providers. At a minimum, we need the `coder` provider.
|
||||
For this template, we also need the `docker` provider:
|
||||
|
||||
```tf
|
||||
terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "~> 0.8.3"
|
||||
}
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
version = "~> 3.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "coder" {
|
||||
}
|
||||
|
||||
provider "docker" {
|
||||
}
|
||||
|
||||
locals {
|
||||
username = data.coder_workspace.me.owner
|
||||
username = data.coder_workspace_owner.me.name
|
||||
}
|
||||
|
||||
data "coder_provisioner" "me" {
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {
|
||||
provider "docker" {
|
||||
}
|
||||
|
||||
provider "coder" {
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {
|
||||
}
|
||||
```
|
||||
|
||||
Notice that the `provider` blocks for `coder` and `docker` are empty. In a more
|
||||
@@ -132,8 +109,7 @@ The
|
||||
[`coder_workspace`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace)
|
||||
data source provides details about the state of a workspace, such as its name,
|
||||
owner, and so on. The data source also lets us know when a workspace is being
|
||||
started or stopped. We'll take advantage of this information in later steps to
|
||||
do these things:
|
||||
started or stopped. We'll use this information in later steps to:
|
||||
|
||||
- Set some environment variables based on the workspace owner.
|
||||
- Manage ephemeral and persistent storage.
|
||||
@@ -147,29 +123,27 @@ runs inside the compute aspect of your workspace, typically a VM or container.
|
||||
In our case, it will run in Docker.
|
||||
|
||||
You do not need to have any open ports on the compute aspect, but the agent
|
||||
needs `curl` access to the Coder server. Remember that we installed `curl` in
|
||||
`Dockerfile`, earlier.
|
||||
needs `curl` access to the Coder server.
|
||||
|
||||
This snippet creates the agent:
|
||||
Add this snippet after the last closing `}` in `main.tf` to create the agent:
|
||||
|
||||
```tf
|
||||
resource "coder_agent" "main" {
|
||||
arch = data.coder_provisioner.me.arch
|
||||
os = "linux"
|
||||
startup_script_timeout = 180
|
||||
startup_script = <<-EOT
|
||||
set -e
|
||||
|
||||
# install and start code-server
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server --version 4.11.0
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
|
||||
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
|
||||
EOT
|
||||
|
||||
env = {
|
||||
GIT_AUTHOR_NAME = "${data.coder_workspace.me.owner}"
|
||||
GIT_COMMITTER_NAME = "${data.coder_workspace.me.owner}"
|
||||
GIT_AUTHOR_EMAIL = "${data.coder_workspace.me.owner_email}"
|
||||
GIT_COMMITTER_EMAIL = "${data.coder_workspace.me.owner_email}"
|
||||
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}"
|
||||
}
|
||||
|
||||
metadata {
|
||||
@@ -188,34 +162,37 @@ resource "coder_agent" "main" {
|
||||
timeout = 1
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Because Docker is running locally in the Coder server, there is no need to
|
||||
authenticate `coder_agent`. But if your `coder_agent` were running on a remote
|
||||
host, your template would need
|
||||
authenticate `coder_agent`. But if your `coder_agent` is running on a remote
|
||||
host, your template will need
|
||||
[authentication credentials](../admin/external-auth.md).
|
||||
|
||||
This template's agent also runs a startup script, sets environment variables,
|
||||
and provides metadata.
|
||||
|
||||
The
|
||||
[`startup script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
installs [code-server](https://coder.com/docs/code-server), a browser-based
|
||||
[VS Code](https://code.visualstudio.com/) app that runs in the workspace. We'll
|
||||
give users access to code-server through `coder_app`, later.
|
||||
- [`startup script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)
|
||||
|
||||
The
|
||||
[`env`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#env)
|
||||
block sets environments variables for the workspace. We use the data source from
|
||||
`coder_workspace` to set the environment variables based on the workspace's
|
||||
owner. This way, the owner can make git commits immediately without any manual
|
||||
configuration.
|
||||
- Installs [code-server](https://coder.com/docs/code-server), a browser-based
|
||||
[VS Code](https://code.visualstudio.com/) app that runs in the workspace.
|
||||
|
||||
Your template can use metadata to show information to the workspace owner. Coder
|
||||
displays this metadata in the Coder dashboard. Our template has
|
||||
[`metadata`](../admin/templates/extending-templates/agent-metadata.md) blocks
|
||||
for CPU and RAM usage.
|
||||
We'll give users access to code-server through `coder_app`, later.
|
||||
|
||||
- [`env` block](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#env)
|
||||
|
||||
- Sets environments variables for the workspace.
|
||||
|
||||
We use the data source from `coder_workspace` to set the environment
|
||||
variables based on the workspace's owner. This way, the owner can make git
|
||||
commits immediately without any manual configuration.
|
||||
|
||||
- [`metadata`](../admin/templates/extending-templates/agent-metadata.md) blocks
|
||||
|
||||
- Your template can use metadata to show information to the workspace owner
|
||||
Coder displays this metadata in the Coder dashboard.
|
||||
|
||||
Our template has `metadata` blocks for CPU and RAM usage.
|
||||
|
||||
## 4. coder_app
|
||||
|
||||
@@ -229,10 +206,9 @@ This is commonly used for
|
||||
[web IDEs](../user-guides/workspace-access/web-ides.md) such as
|
||||
[code-server](https://coder.com/docs/code-server), RStudio, and JupyterLab.
|
||||
|
||||
To install and code-server in the workspace, remember that we installed it in
|
||||
the `startup_script` argument in `coder_agent`. We make it available from a
|
||||
workspace with a `coder_app` resource. See
|
||||
[web IDEs](../user-guides/workspace-access/web-ides.md) for more examples.
|
||||
We installed code-server in the `startup_script` argument. To add code-server to
|
||||
the workspace, make it available in the workspace with a `coder_app` resource.
|
||||
See [web IDEs](../user-guides/workspace-access/web-ides.md) for more examples:
|
||||
|
||||
```tf
|
||||
resource "coder_app" "code-server" {
|
||||
@@ -250,11 +226,10 @@ resource "coder_app" "code-server" {
|
||||
threshold = 6
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
You can also use a `coder_app` resource to link to external apps, such as links
|
||||
to wikis or cloud consoles.
|
||||
to wikis or cloud consoles:
|
||||
|
||||
```tf
|
||||
resource "coder_app" "coder-server-doc" {
|
||||
@@ -264,7 +239,6 @@ resource "coder_app" "coder-server-doc" {
|
||||
url = "https://coder.com/docs/code-server"
|
||||
external = true
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 5. Persistent and ephemeral resources
|
||||
@@ -283,10 +257,9 @@ We do this in 2 parts:
|
||||
workspace name change, we use an immutable parameter, like
|
||||
`data.coder_workspace.me.id`.
|
||||
|
||||
You'll see later that we make sure that our Docker container is ephemeral with
|
||||
the Terraform
|
||||
Later, we use the Terraform
|
||||
[count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
|
||||
meta-argument.
|
||||
meta-argument to make sure that our Docker container is ephemeral.
|
||||
|
||||
```tf
|
||||
resource "docker_volume" "home_volume" {
|
||||
@@ -296,7 +269,6 @@ resource "docker_volume" "home_volume" {
|
||||
ignore_changes = all
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For details, see
|
||||
@@ -305,7 +277,7 @@ For details, see
|
||||
## 6. Set up the Docker container
|
||||
|
||||
To set up our Docker container, our template has a `docker_image` resource that
|
||||
uses `build/Dockerfile`, which we created earlier.
|
||||
uses `build/Dockerfile`, which we created earlier:
|
||||
|
||||
```tf
|
||||
resource "docker_image" "main" {
|
||||
@@ -320,7 +292,6 @@ resource "docker_image" "main" {
|
||||
dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Our `docker_container` resource uses `coder_workspace` `start_count` to start
|
||||
@@ -331,7 +302,7 @@ resource "docker_container" "workspace" {
|
||||
count = data.coder_workspace.me.start_count
|
||||
image = docker_image.main.name
|
||||
# Uses lower() to avoid Docker restriction on container names.
|
||||
name = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
|
||||
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
|
||||
# Hostname makes the shell more user friendly: coder@my-workspace:~$
|
||||
hostname = data.coder_workspace.me.name
|
||||
# Use the docker gateway if the access URL is 127.0.0.1
|
||||
@@ -349,7 +320,6 @@ resource "docker_container" "workspace" {
|
||||
read_only = false
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 7. Create the template in Coder
|
||||
@@ -359,59 +329,102 @@ Save `main.tf` and exit the editor.
|
||||
Now that we've created the files for our template, we can add them to our Coder
|
||||
deployment.
|
||||
|
||||
We can do this with the Coder CLI or the Coder dashboard. For this tour, we'll
|
||||
We can do this with the Coder CLI or the Coder dashboard. In this example, we'll
|
||||
use the Coder CLI.
|
||||
|
||||
First, you'll need to log in to your Coder deployment from the CLI. This is
|
||||
where you need the URL for your deployment:
|
||||
1. Log in to your Coder deployment from the CLI. This is where you need the URL
|
||||
for your deployment:
|
||||
|
||||
```sh
|
||||
$ coder login https://coder.example.com
|
||||
Your browser has been opened to visit:
|
||||
```console
|
||||
$ coder login https://coder.example.com
|
||||
Attempting to authenticate with config URL: 'https://coder.example.com'
|
||||
Open the following in your browser:
|
||||
|
||||
https://coder.example.com/cli-auth
|
||||
https://coder.example.com/cli-auth
|
||||
|
||||
> Paste your token here:
|
||||
```
|
||||
> Paste your token here:
|
||||
```
|
||||
|
||||
In your web browser, enter your credentials:
|
||||
1. In your web browser, enter your credentials:
|
||||
|
||||

|
||||
<Image height="412px" src="../images/templates/coder-login-web.png" alt="Log in to your Coder deployment" align="center" />
|
||||
|
||||
Copy the session token into the clipboard:
|
||||
1. Copy the session token to the clipboard:
|
||||
|
||||

|
||||
<Image height="472px" src="../images/templates/coder-session-token.png" alt="Copy session token" align="center" />
|
||||
|
||||
And paste it into the CLI:
|
||||
1. Paste it into the CLI:
|
||||
|
||||
```sh
|
||||
> Welcome to Coder, marc! You're authenticated.
|
||||
$
|
||||
```
|
||||
```output
|
||||
> Welcome to Coder, marc! You're authenticated.
|
||||
$
|
||||
```
|
||||
|
||||
Now you can add your template files to your Coder deployment:
|
||||
### Add the template files to Coder
|
||||
|
||||
```sh
|
||||
$ pwd
|
||||
/home/marc/template-tour
|
||||
$ coder templates create
|
||||
> Upload "."? (yes/no) yes
|
||||
```
|
||||
Add your template files to your Coder deployment. You can upload the template
|
||||
through the CLI, or through the Coder dashboard:
|
||||
|
||||
The Coder CLI tool gives progress information then prompts you to confirm:
|
||||
<div class="tabs">
|
||||
|
||||
```sh
|
||||
> Confirm create? (yes/no) yes
|
||||
#### CLI
|
||||
|
||||
The template-tour template has been created! Developers can provision a workspace with this template using:
|
||||
1. Run `coder templates create` from the directory with your template files:
|
||||
|
||||
```console
|
||||
$ pwd
|
||||
/home/docs/template-tour
|
||||
$ coder templates push
|
||||
> Upload "."? (yes/no) yes
|
||||
```
|
||||
|
||||
1. The Coder CLI tool gives progress information then prompts you to confirm:
|
||||
|
||||
```console
|
||||
> Confirm create? (yes/no) yes
|
||||
|
||||
The template-tour template has been created! Developers can provision a workspace with this template using:
|
||||
|
||||
coder create --template="template-tour" [workspace name]
|
||||
```
|
||||
```
|
||||
|
||||
In your web browser, log in to your Coder dashboard, select **Templates**. Your
|
||||
template is ready to use for new workspaces.
|
||||
1. In your web browser, log in to your Coder dashboard, select **Templates**.
|
||||
|
||||

|
||||
1. Once the upload completes, select **Templates** from the top to deploy it to
|
||||
a new workspace.
|
||||
|
||||

|
||||
|
||||
#### Dashboard
|
||||
|
||||
1. Create a `.zip` of the template files.
|
||||
|
||||
- On Mac or Windows, highlight the files and then right click. A "compress"
|
||||
option is available through the right-click context menu.
|
||||
|
||||
- To zip the files through the command line:
|
||||
|
||||
```shell
|
||||
zip templates.zip Dockerfile main.tf
|
||||
```
|
||||
|
||||
1. Select **Templates** from the top of the Coder dashboard, then **Create
|
||||
Template**.
|
||||
1. Select **Upload template**:
|
||||
|
||||

|
||||
|
||||
1. Drag the `.zip` file into the **Upload template** section and fill out the
|
||||
details, then select **Create template**.
|
||||
|
||||

|
||||
|
||||
1. Once the upload completes, select **Templates** from the top to deploy it to
|
||||
a new workspace.
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### Next steps
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export const TemplateUpload: FC<TemplateUploadProps> = ({
|
||||
>
|
||||
starter templates
|
||||
</Link>{" "}
|
||||
to getting started with Coder.
|
||||
to get started with Coder.
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||