2021-06-02 16:53:39 +02:00
---
2021-07-16 18:37:29 +02:00
slug: /1004/dev-first-env/
2021-06-02 16:53:39 +02:00
---
2021-07-16 18:37:29 +02:00
# Create your first Dagger environment
2021-02-08 20:47:07 +01:00
2021-06-10 20:56:41 +02:00
## Overview
2021-03-18 06:44:50 +01:00
2021-06-29 14:26:42 +02:00
In this guide, you will create your first Dagger environment from scratch,
and use it to deploy a React application to two locations in parallel:
2021-06-10 20:56:41 +02:00
a dedicated [Amazon S3 ](https://wikipedia.org/wiki/Amazon_S3 ) bucket, and a
[Netlify ](https://en.wikipedia.org/wiki/Netlify ) site.
2021-05-01 09:15:03 +02:00
2021-06-10 20:56:41 +02:00
### Anatomy of a Dagger environment
2021-05-01 09:46:49 +02:00
2021-06-29 14:26:42 +02:00
A Dagger environment contains all the code and data necessary to deliver a particular application in a specific way.
For example, the same application might be delivered to a production and staging environment, each with its own configuration.
2021-05-01 09:46:49 +02:00
2021-06-10 20:56:41 +02:00
An environment is made of 3 parts:
2021-05-01 09:15:03 +02:00
2021-06-22 17:45:08 +02:00
- A _plan_ , authored by the environment's _developer_ , using the [Cue ](https://cuelang.org ) language.
2021-05-01 09:15:03 +02:00
2021-06-29 14:26:42 +02:00
- _Inputs_, supplied by the environment's _user_ via the `dagger input` command and written to a particular file. Inputs may be configuration values, artifacts, or encrypted secrets.
2021-05-01 09:15:03 +02:00
2021-06-29 14:26:42 +02:00
- _Outputs_, computed by the Dagger engine via the `dagger up` command and recorded to a particular directory.
2021-06-10 20:56:41 +02:00
2021-06-29 14:26:42 +02:00
We will first develop our environment's _plan_ , configure its initial inputs, then finally run it to verify that it works.
2021-06-10 20:56:41 +02:00
### Anatomy of a plan
2021-06-29 14:26:42 +02:00
A _plan_ specifies, in code, how to deliver a particular application in a specific way.
2021-06-10 20:56:41 +02:00
It is your environment's source code.
2021-06-29 14:26:42 +02:00
Unlike regular imperative programs, which specify a sequence of instructions to execute,
2021-06-10 20:56:41 +02:00
a Dagger plan is _declarative_ : it lays out your application's supply chain as a graph
of interconnected nodes.
Each node in the graph represents a component of the supply chain, for example:
2021-06-22 17:45:08 +02:00
- Development tools: source control, CI, build systems, testing systems
- Hosting infrastructure: compute, storage, networking, databases, CDNs
- Software dependencies: operating systems, languages, libraries, frameworks, etc.
2021-06-10 20:56:41 +02:00
Each link in the graph represents a flow of data between nodes. For example:
2021-06-22 17:45:08 +02:00
- source code flows from a git repository to a build system
- system dependencies are combined in a docker image, then uploaded to a registry
- configuration files are generated then sent to a compute cluster or load balancer
2021-06-10 20:56:41 +02:00
### Introduction to Cue development
2021-06-16 03:39:47 +02:00
Dagger delivery plans are developed in Cue.
2021-06-16 15:44:13 +02:00
Cue is a powerful declarative language by Marcel van Lohuizen. Marcel co-created the Borg Configuration Language (BCL), the [language used to deploy all applications at Google ](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/43438.pdf ). It is a superset of JSON, with additional features to make declarative, data-driven programming as pleasant and productive as regular imperative programming.
2021-06-10 20:56:41 +02:00
If you are new to Cue development, don't worry: this tutorial will walk you through the basic
steps to get started, and give you resources to learn more.
2021-06-29 14:26:42 +02:00
In technical terms, our plan is a [Cue Package ](https://cuelang.org/docs/concepts/packages/#packages ). This tutorial will develop a new Cue package from scratch for our plan, but you can use any Cue package as a plan.
2021-05-01 09:15:03 +02:00
2021-06-16 18:54:28 +02:00
## Initial setup
2021-06-10 20:56:41 +02:00
### Install Cue
2021-06-29 14:26:42 +02:00
Although not strictly necessary, for an optimal development experience, we recommend
2021-06-16 16:33:17 +02:00
[installing a recent version of Cue ](https://github.com/cuelang/cue/releases/ ).
2021-06-10 20:56:41 +02:00
2021-06-16 18:54:28 +02:00
### Prepare Cue learning resources
2021-06-10 20:56:41 +02:00
If you are new to Cue, we recommend keeping the following resources in browser tabs:
2021-08-13 01:47:59 +02:00
- The unofficial but excellent [Cuetorials ](https://cuetorials.com/overview/foundations/ ) in a browser tab, to look up Cue concepts as they appear.
2021-06-10 20:56:41 +02:00
2021-06-22 17:45:08 +02:00
- The official [Cue interactive sandbox ](https://cuelang.org/play ) for easy experimentation.
2021-06-10 20:56:41 +02:00
### Setup example app
You will need a local copy of the [Dagger examples repository ](https://github.com/dagger/examples ).
2021-06-16 16:34:44 +02:00
NOTE: you may use the same local copy across all tutorials.
2021-06-10 20:56:41 +02:00
2021-06-16 15:48:49 +02:00
```shell
2021-06-10 20:56:41 +02:00
git clone https://github.com/dagger/examples
2021-06-07 15:44:45 +02:00
```
2021-05-01 09:15:03 +02:00
2021-06-16 15:14:47 +02:00
Make sure that all commands are run from the `todoapp` directory:
2021-05-01 09:15:03 +02:00
2021-06-16 15:48:49 +02:00
```shell
2021-06-16 15:14:47 +02:00
cd examples/todoapp
2021-06-10 20:56:41 +02:00
```
2021-06-16 18:54:28 +02:00
## Develop the plan
2021-06-10 20:56:41 +02:00
### Initialize a Cue module
2021-06-16 03:39:47 +02:00
Developing for Dagger takes place in a [Cue module ](https://cuelang.org/docs/concepts/packages/#modules ).
2021-06-10 20:56:41 +02:00
If you are familiar with Go, Cue modules are directly inspired by Go modules.
2021-06-29 14:26:42 +02:00
Otherwise, don't worry: a Cue module is simply a directory with one or more Cue packages in it. For example, a Cue module has a `cue.mod` directory at its root.
2021-06-10 20:56:41 +02:00
2021-09-08 22:31:47 +02:00
This guide will use the same directory as the root of the Dagger workspace and the Cue module, but you can create your Cue module anywhere inside the Dagger workspace. In general, you won't have to worry about it at all. You will initialize a dagger workspace with the following command.
2021-05-26 00:20:44 +02:00
2021-06-16 15:48:49 +02:00
```shell
2021-09-08 22:31:47 +02:00
dagger init # Optional, already present in `todoapp`
2021-06-07 15:44:45 +02:00
```
2021-05-26 00:20:44 +02:00
2021-09-08 22:31:47 +02:00
> In our case, `todoapp` already contains a workspace, so this step is optional.
2021-06-16 18:54:28 +02:00
### Create a Cue package
2021-05-01 09:15:03 +02:00
2021-06-10 20:56:41 +02:00
Now we start developing our Cue package at the root of our Cue module.
2021-05-01 09:15:03 +02:00
2021-06-29 14:26:42 +02:00
In this guide, we will split our package into multiple files, one per component.
Thus, it is typical for a Cue package to have only one file. However, you can organize your package any way you want: the Cue evaluator merges all files from the same package, as long as they are in the same directory, and start with the same
`package` clause...
2021-06-10 20:56:41 +02:00
See the [Cue documentation ](https://cuelang.org/docs/concepts/packages/#files-belonging-to-a-package ) for more details.
2021-05-01 09:15:03 +02:00
2021-06-10 20:56:41 +02:00
We will call our package `multibucket` because it sounds badass and vaguely explains what it does.
But you can call your packages anything you want.
2021-05-01 09:15:03 +02:00
2021-06-16 17:31:31 +02:00
Let's create a new directory for our Cue package:
2021-05-01 09:15:03 +02:00
2021-06-16 15:48:49 +02:00
```shell
2021-07-02 03:57:43 +02:00
mkdir multibucket
2021-05-01 09:15:03 +02:00
```
2021-06-10 20:56:41 +02:00
### Component 1: app source code
2021-05-22 00:02:18 +02:00
2021-06-10 20:56:41 +02:00
The first component of our plan is the source code of our React application.
2021-05-01 09:15:03 +02:00
2021-06-29 14:26:42 +02:00
In Dagger terms, this component has two essential properties:
2021-05-01 09:15:03 +02:00
2021-06-22 17:45:08 +02:00
1. It is an _artifact_ : something that can be represented as a directory.
2021-06-29 14:26:42 +02:00
2. It is an _input_ : something that is provided by the end-user.
2021-05-01 09:15:03 +02:00
2021-06-16 17:31:31 +02:00
Let's write the corresponding Cue code to a new file in our package:
2021-05-01 09:15:03 +02:00
2021-08-13 01:47:59 +02:00
```cue file=./tests/multibucket/source.cue title="todoapp/cue.mod/multibucket/source.cue"
2021-05-01 09:15:03 +02:00
```
2021-07-02 03:57:43 +02:00
This code defines a component at the key `src` and specifies that it is both an artifact and an input.
2021-05-01 09:15:03 +02:00
2021-06-10 20:56:41 +02:00
### Component 2: yarn package
2021-05-01 09:15:03 +02:00
2021-06-16 17:31:31 +02:00
The second component of our plan is the Yarn package built from the app source code:
2021-05-01 09:15:03 +02:00
2021-08-13 01:47:59 +02:00
```cue file=./tests/multibucket/yarn.cue title="todoapp/cue.mod/multibucket/yarn.cue"
2021-06-10 20:56:41 +02:00
```
2021-06-07 15:44:45 +02:00
2021-06-10 20:56:41 +02:00
Let's break it down:
2021-06-07 15:44:45 +02:00
2021-06-22 17:45:08 +02:00
- `package multibucket` : this file is part of the multibucket package
2021-06-23 16:31:42 +02:00
- `import ( "alpha.dagger.io/js/yarn" )` : import a package from the [Dagger Universe ](../reference/universe/README.md ).
2021-06-22 17:45:08 +02:00
- `app: yarn.#Package` : apply the `#Package` definition at the key `app`
- `&` : also merge the following values at the same key...
2021-06-29 14:26:42 +02:00
- `{ source: src }` : set the key `app.source` to the value of `src` . This snippet of code connects our two components, forming the first link in our DAG
2021-06-07 15:44:45 +02:00
2021-06-10 20:56:41 +02:00
### Component 3: dedicated S3 bucket
2021-05-01 09:15:03 +02:00
2021-06-29 14:26:42 +02:00
_FIXME_: this section is not yet available because the [Amazon S3 package ](https://github.com/dagger/dagger/tree/main/stdlib/aws/s3 ) does [not yet support bucket creation ](https://github.com/dagger/dagger/issues/623 ). We welcome external contributions :)
2021-06-07 15:44:45 +02:00
2021-06-10 20:56:41 +02:00
### Component 4: deploy to Netlify
2021-06-07 15:44:45 +02:00
2021-06-16 17:31:31 +02:00
The third component of our plan is the Netlify site to which the app will be deployed:
2021-03-25 09:56:26 +01:00
2021-08-13 01:47:59 +02:00
```cue file=./tests/multibucket/netlify.cue title="todoapp/cue.mod/multibucket/netlify.cue"
2021-06-10 20:56:41 +02:00
```
2021-05-22 00:02:18 +02:00
2021-06-29 14:26:42 +02:00
This component is very similar to the previous one:
2021-04-24 03:00:00 +02:00
2021-06-22 17:45:08 +02:00
- We use the same package name as the other files
2021-06-23 10:53:03 +02:00
- We import another package from the [Dagger Universe ](../reference/universe/README.md ).
2021-06-22 17:45:08 +02:00
- `site: "netlify": site.#Netlify` : apply the `#Site` definition at the key `site.netlify` . Note the use of quotes to protect the key from name conflict.
- `&` : also merge the following values at the same key...
2021-06-29 14:26:42 +02:00
- `{ contents: app.build }` : set the key `site.netlify.contents` to the value of `app.build` . This line connects our components 2 and 3, forming the second link in our DAG.
2021-04-24 03:00:00 +02:00
2021-06-10 20:56:41 +02:00
### Exploring a package documentation
2021-04-24 03:00:00 +02:00
2021-06-10 20:56:41 +02:00
But wait: how did we know what fields were available in `yarn.#Package` and `netlify.#Site` ?
2021-06-23 10:53:03 +02:00
Answer: thanks to the `dagger doc` command, which prints the documentation of any package from [Dagger Universe ](../reference/universe/README.md ).
2021-04-24 03:00:00 +02:00
2021-06-16 15:48:49 +02:00
```shell
2021-06-27 15:07:52 +02:00
dagger doc alpha.dagger.io/netlify
dagger doc alpha.dagger.io/js/yarn
2021-06-10 20:56:41 +02:00
```
2021-04-24 03:00:00 +02:00
2021-06-23 10:53:03 +02:00
You can also browse the [Dagger Universe ](../reference/universe/README.md ) reference in the documentation.
2021-02-08 20:47:07 +01:00
2021-06-10 20:56:41 +02:00
## Setup the environment
2021-02-08 20:47:07 +01:00
2021-06-10 20:56:41 +02:00
### Create a new environment
2021-02-08 20:47:07 +01:00
2021-06-16 16:39:37 +02:00
Now that your Cue package is ready, let's create an environment to run it:
2021-03-27 01:13:43 +01:00
2021-06-16 15:48:49 +02:00
```shell
2021-07-10 17:03:25 +02:00
dagger new 'multibucket' -p ./multibucket
2021-06-10 20:56:41 +02:00
```
2021-05-22 00:02:18 +02:00
2021-06-28 19:38:29 +02:00
### Configure user inputs
2021-03-27 01:13:43 +01:00
2021-06-28 19:38:29 +02:00
You can inspect the list of inputs (both required and optional) using dagger input list:
2021-03-27 01:13:43 +01:00
2021-06-16 15:48:49 +02:00
```shell
2021-06-28 19:38:29 +02:00
dagger input list -e multibucket
# Input Value Set by user Description
# site.netlify.account.name *"" | string false Use this Netlify account name (also referred to as "team" in the Netlify docs)
# site.netlify.account.token dagger.#Secret false Netlify authentication token
# site.netlify.name string false Deploy to this Netlify site
# site.netlify.create *true | bool false Create the Netlify site if it doesn't exist?
# src dagger.#Artifact false Source code of the sample application
# app.cwd *"." | string false working directory to use
# app.writeEnvFile *"" | string false Write the contents of `environment` to this file, in the "envfile" format
# app.buildDir *"build" | string false Read build output from this directory (path must be relative to working directory)
# app.script *"build" | string false Run this yarn script
# app.args *[] | [] false Optional arguments for the script
2021-06-10 20:56:41 +02:00
```
2021-02-08 20:47:07 +01:00
2021-06-28 19:38:29 +02:00
All the values without default values (without `*` ) have to be specified by the user. Here, required fields are:
2021-03-18 06:44:50 +01:00
2021-06-28 19:38:29 +02:00
- `site.netlify.account.token` , your access token
- `site.netlify.name` , name of the published website
- `src` , source code of the app
2021-03-18 06:44:50 +01:00
2021-07-02 03:57:43 +02:00
Please note the type of the user inputs: a string, a #Secret , and an artifact. Let's see how to input them:
2021-06-28 19:38:29 +02:00
```shell
# As a string input is expected for `site.netlify.name`, we set a `text` input
dagger input text site.netlify.name < GLOBALLY-UNIQUE-NAME > -e multibucket
# As a secret input is expected for `site.netlify.account.token`, we set a `secret` input
dagger input secret site.netlify.account.token < PERSONAL-ACCESS-TOKEN > -e multibucket
2021-07-02 03:57:43 +02:00
# As an Artifact is expected for `src`, we set a `dir` input (dagger input list for alternatives)
2021-06-28 19:38:29 +02:00
dagger input dir src . -e multibucket
```
2021-03-18 06:44:50 +01:00
2021-06-10 20:56:41 +02:00
### Deploy
2021-03-18 06:44:50 +01:00
2021-07-02 03:57:43 +02:00
Now that everything is appropriately set, let's deploy on Netlify:
2021-06-28 19:38:29 +02:00
```shell
dagger up -e multibucket
```
2021-06-10 20:56:41 +02:00
### Using the environment
2021-03-27 01:13:43 +01:00
2021-06-10 20:56:41 +02:00
[This section is not yet written ](https://github.com/dagger/dagger/blob/main/CONTRIBUTING.md )
2021-03-26 23:57:52 +01:00
2021-06-10 20:56:41 +02:00
## Share your environment
2021-03-26 23:57:52 +01:00
2021-06-10 20:56:41 +02:00
### Introduction to gitops
2021-03-26 23:57:52 +01:00
2021-06-10 20:56:41 +02:00
[This section is not yet written ](https://github.com/dagger/dagger/blob/main/CONTRIBUTING.md )
2021-03-27 01:13:43 +01:00
2021-06-10 20:56:41 +02:00
### Review changes
2021-03-27 01:13:43 +01:00
2021-06-10 20:56:41 +02:00
[This section is not yet written ](https://github.com/dagger/dagger/blob/main/CONTRIBUTING.md )
2021-03-27 01:13:43 +01:00
2021-06-10 20:56:41 +02:00
### Commit changes
2021-03-27 01:13:43 +01:00
2021-06-10 20:56:41 +02:00
[This section is not yet written ](https://github.com/dagger/dagger/blob/main/CONTRIBUTING.md )