Merge branch 'main' into project-info-cmd
This commit is contained in:
commit
69ce99d020
42
.github/workflows/dagger-ci.yml
vendored
42
.github/workflows/dagger-ci.yml
vendored
@ -45,41 +45,21 @@ jobs:
|
|||||||
- name: "Expose GitHub Runtime"
|
- name: "Expose GitHub Runtime"
|
||||||
uses: crazy-max/ghaction-github-runtime@v1
|
uses: crazy-max/ghaction-github-runtime@v1
|
||||||
|
|
||||||
- name: Prepare dagger
|
# - name: "Set up dagger from source"
|
||||||
run: |
|
# run: |
|
||||||
make dagger
|
# make dagger
|
||||||
cp ./cmd/dagger/dagger /usr/local/bin
|
# cp ./cmd/dagger/dagger /usr/local/bin
|
||||||
|
|
||||||
|
- name: "Set up dagger"
|
||||||
|
uses: dagger/dagger-for-github@v2
|
||||||
|
with:
|
||||||
|
install-only: true
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
|
DAGGER_LOG_LEVEL: "debug"
|
||||||
|
DAGGER_LOG_FORMAT: "plain"
|
||||||
DAGGER_CACHE_TO: "type=gha,mode=max,scope=dagger-ci-build"
|
DAGGER_CACHE_TO: "type=gha,mode=max,scope=dagger-ci-build"
|
||||||
DAGGER_CACHE_FROM: "type=gha,scope=dagger-ci-build"
|
DAGGER_CACHE_FROM: "type=gha,scope=dagger-ci-build"
|
||||||
run: |
|
run: |
|
||||||
dagger do build
|
dagger do build
|
||||||
|
|
||||||
lint:
|
|
||||||
name: "Lint"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: "Setup Go"
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.16
|
|
||||||
|
|
||||||
- name: "Expose GitHub Runtime"
|
|
||||||
uses: crazy-max/ghaction-github-runtime@v1
|
|
||||||
|
|
||||||
- name: Prepare dagger
|
|
||||||
run: |
|
|
||||||
make dagger
|
|
||||||
cp ./cmd/dagger/dagger /usr/local/bin
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
env:
|
|
||||||
DAGGER_CACHE_TO: "type=gha,mode=max,scope=dagger-ci-lint"
|
|
||||||
DAGGER_CACHE_FROM: "type=gha,scope=dagger-ci-lint"
|
|
||||||
run: |
|
|
||||||
dagger do lint
|
|
||||||
|
81
.github/workflows/lint.yml
vendored
81
.github/workflows/lint.yml
vendored
@ -4,27 +4,27 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- '**.go'
|
- "**.go"
|
||||||
- '**.sh'
|
- "**.sh"
|
||||||
- '**.bash'
|
- "**.bash"
|
||||||
- '**.cue'
|
- "**.cue"
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '.golangci.yml'
|
- ".golangci.yml"
|
||||||
- 'Makefile'
|
- "Makefile"
|
||||||
- 'README.md'
|
- "README.md"
|
||||||
- '.github/workflows/lint.yml'
|
- ".github/workflows/lint.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- '**.go'
|
- "**.go"
|
||||||
- '**.sh'
|
- "**.sh"
|
||||||
- '**.bash'
|
- "**.bash"
|
||||||
- '**.cue'
|
- "**.cue"
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '.golangci.yml'
|
- ".golangci.yml"
|
||||||
- 'Makefile'
|
- "Makefile"
|
||||||
- 'README.md'
|
- "README.md"
|
||||||
- '.github/workflows/lint.yml'
|
- ".github/workflows/lint.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
@ -41,35 +41,24 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version: 1.16
|
go-version: 1.16
|
||||||
|
|
||||||
- name: "Install deps"
|
- name: "Expose GitHub Runtime"
|
||||||
run: |
|
uses: crazy-max/ghaction-github-runtime@v1
|
||||||
# Cue
|
|
||||||
export CUE_VERSION="$(grep cue ./go.mod | cut -d' ' -f2 | head -1 | sed -E 's/\.[[:digit:]]\.[[:alnum:]]+-[[:alnum:]]+$//')"
|
|
||||||
export CUE_TARBALL="cue_${CUE_VERSION}_linux_amd64.tar.gz"
|
|
||||||
echo "Installing cue version $CUE_VERSION"
|
|
||||||
curl -L https://github.com/cue-lang/cue/releases/download/${CUE_VERSION}/${CUE_TARBALL} | sudo tar zxf - -C /usr/local/bin
|
|
||||||
|
|
||||||
- name: "Lint go"
|
# - name: "Set up dagger from source"
|
||||||
uses: golangci/golangci-lint-action@v2
|
# run: |
|
||||||
|
# make dagger
|
||||||
|
# cp ./cmd/dagger/dagger /usr/local/bin
|
||||||
|
|
||||||
|
- name: "Set up dagger"
|
||||||
|
uses: dagger/dagger-for-github@v2
|
||||||
with:
|
with:
|
||||||
version: v1.45
|
install-only: true
|
||||||
skip-go-installation: true
|
|
||||||
args: --timeout=3m
|
|
||||||
|
|
||||||
- name: "Lint shell"
|
- name: Lint
|
||||||
|
env:
|
||||||
|
DAGGER_LOG_LEVEL: "debug"
|
||||||
|
DAGGER_LOG_FORMAT: "plain"
|
||||||
|
DAGGER_CACHE_TO: "type=gha,mode=max,scope=dagger-ci-lint"
|
||||||
|
DAGGER_CACHE_FROM: "type=gha,scope=dagger-ci-lint"
|
||||||
run: |
|
run: |
|
||||||
make shellcheck
|
dagger do lint
|
||||||
|
|
||||||
- name: "Lint CUE"
|
|
||||||
run: |
|
|
||||||
make cuelint
|
|
||||||
|
|
||||||
- name: "Lint docs"
|
|
||||||
run: |
|
|
||||||
make docslint
|
|
||||||
|
|
||||||
- name: "Lint markdown"
|
|
||||||
uses: avto-dev/markdown-lint@v1
|
|
||||||
with:
|
|
||||||
config: ".markdownlint.yaml"
|
|
||||||
args: ./docs README.md
|
|
||||||
|
19
Makefile
19
Makefile
@ -33,23 +33,24 @@ test: # Run all tests
|
|||||||
go test -race -v ./...
|
go test -race -v ./...
|
||||||
|
|
||||||
.PHONY: golint
|
.PHONY: golint
|
||||||
golint: # Go lint
|
golint: dagger # Go lint
|
||||||
golangci-lint run --timeout 3m
|
./cmd/dagger/dagger do lint go
|
||||||
|
|
||||||
.PHONY: cuefmt
|
.PHONY: cuefmt
|
||||||
cuefmt: # Format all cue files
|
cuefmt: # Format all cue files
|
||||||
find . -name '*.cue' -not -path '*/cue.mod/*' -print | time xargs -n 1 -P 8 cue fmt -s
|
find . -name '*.cue' -not -path '*/cue.mod/*' -print | time xargs -n 1 -P 8 cue fmt -s
|
||||||
|
|
||||||
.PHONY: cuelint
|
.PHONY: cuelint
|
||||||
cuelint: cuefmt # Lint and format all cue files
|
cuelint: dagger # Lint all cue files
|
||||||
@test -z "$$(git status -s . | grep -e "^ M" | grep "\.cue" | cut -d ' ' -f3 | tee /dev/stderr)"
|
./cmd/dagger/dagger do lint cue
|
||||||
|
|
||||||
.PHONY: shellcheck
|
.PHONY: shellcheck
|
||||||
shellcheck: # Run shellcheck
|
shellcheck: dagger # Run shellcheck
|
||||||
shellcheck $$(find . -type f \( -iname \*.bats -o -iname \*.bash -o -iname \*.sh \) -not -path "*/node_modules/*" -not -path "*/bats-*/*")
|
./cmd/dagger/dagger do lint shell
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: shellcheck cuelint golint docslint mdlint # Lint everything
|
lint: dagger # Lint everything
|
||||||
|
./cmd/dagger/dagger do lint
|
||||||
|
|
||||||
.PHONY: integration
|
.PHONY: integration
|
||||||
integration: core-integration universe-test doc-test # Run all integration tests
|
integration: core-integration universe-test doc-test # Run all integration tests
|
||||||
@ -78,10 +79,6 @@ doc-test: dagger-debug # Test docs
|
|||||||
docs: dagger # Generate docs
|
docs: dagger # Generate docs
|
||||||
DAGGER_TELEMETRY_DISABLE=1 ./cmd/dagger/dagger doc --output ./docs/reference --format md
|
DAGGER_TELEMETRY_DISABLE=1 ./cmd/dagger/dagger doc --output ./docs/reference --format md
|
||||||
|
|
||||||
.PHONY: docslint
|
|
||||||
docslint: docs # Generate & lint docs
|
|
||||||
@test -z "$$(git status -s . | grep -e "^ M" | grep docs/reference | cut -d ' ' -f3 | tee /dev/stderr)"
|
|
||||||
|
|
||||||
.PHONY: mdlint
|
.PHONY: mdlint
|
||||||
mdlint: # Markdown lint for web
|
mdlint: # Markdown lint for web
|
||||||
@markdownlint ./docs README.md
|
@markdownlint ./docs README.md
|
||||||
|
46
ci.cue
46
ci.cue
@ -5,12 +5,12 @@ import (
|
|||||||
|
|
||||||
"universe.dagger.io/bash"
|
"universe.dagger.io/bash"
|
||||||
"universe.dagger.io/alpine"
|
"universe.dagger.io/alpine"
|
||||||
"universe.dagger.io/docker"
|
|
||||||
"universe.dagger.io/go"
|
"universe.dagger.io/go"
|
||||||
|
|
||||||
"github.com/dagger/dagger/ci/golangci"
|
"github.com/dagger/dagger/ci/golangci"
|
||||||
"github.com/dagger/dagger/ci/shellcheck"
|
"github.com/dagger/dagger/ci/shellcheck"
|
||||||
"github.com/dagger/dagger/ci/markdownlint"
|
"github.com/dagger/dagger/ci/markdownlint"
|
||||||
|
"github.com/dagger/dagger/ci/cue"
|
||||||
)
|
)
|
||||||
|
|
||||||
dagger.#Plan & {
|
dagger.#Plan & {
|
||||||
@ -97,48 +97,8 @@ dagger.#Plan & {
|
|||||||
files: ["./docs", "README.md"]
|
files: ["./docs", "README.md"]
|
||||||
}
|
}
|
||||||
|
|
||||||
cue: docker.#Build & {
|
"cue": cue.#Lint & {
|
||||||
// FIXME: spin off into its own package?
|
source: _source
|
||||||
steps: [
|
|
||||||
alpine.#Build & {
|
|
||||||
packages: bash: _
|
|
||||||
packages: curl: _
|
|
||||||
packages: git: _
|
|
||||||
},
|
|
||||||
|
|
||||||
docker.#Copy & {
|
|
||||||
contents: _source
|
|
||||||
source: "go.mod"
|
|
||||||
dest: "go.mod"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Install CUE
|
|
||||||
bash.#Run & {
|
|
||||||
script: contents: #"""
|
|
||||||
export CUE_VERSION="$(grep cue ./go.mod | cut -d' ' -f2 | head -1 | sed -E 's/\.[[:digit:]]\.[[:alnum:]]+-[[:alnum:]]+$//')"
|
|
||||||
export CUE_TARBALL="cue_${CUE_VERSION}_linux_amd64.tar.gz"
|
|
||||||
echo "Installing cue version $CUE_VERSION"
|
|
||||||
curl -L "https://github.com/cue-lang/cue/releases/download/${CUE_VERSION}/${CUE_TARBALL}" | tar zxf - -C /usr/local/bin
|
|
||||||
cue version
|
|
||||||
"""#
|
|
||||||
},
|
|
||||||
|
|
||||||
// CACHE: copy only *.cue files
|
|
||||||
docker.#Copy & {
|
|
||||||
contents: _source
|
|
||||||
include: ["*.cue"]
|
|
||||||
dest: "/cue"
|
|
||||||
},
|
|
||||||
|
|
||||||
// LINT
|
|
||||||
bash.#Run & {
|
|
||||||
workdir: "/cue"
|
|
||||||
script: contents: #"""
|
|
||||||
find . -name '*.cue' -not -path '*/cue.mod/*' -print | time xargs -t -n 1 -P 8 cue fmt -s
|
|
||||||
test -z "$(git status -s . | grep -e "^ M" | grep "\.cue" | cut -d ' ' -f3 | tee /dev/stderr)"
|
|
||||||
"""#
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
ci/cue/lint.cue
Normal file
56
ci/cue/lint.cue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package cue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dagger.io/dagger"
|
||||||
|
|
||||||
|
"universe.dagger.io/alpine"
|
||||||
|
"universe.dagger.io/docker"
|
||||||
|
"universe.dagger.io/bash"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Lint: {
|
||||||
|
source: dagger.#FS
|
||||||
|
|
||||||
|
docker.#Build & {
|
||||||
|
steps: [
|
||||||
|
alpine.#Build & {
|
||||||
|
packages: bash: _
|
||||||
|
packages: curl: _
|
||||||
|
packages: git: _
|
||||||
|
},
|
||||||
|
|
||||||
|
docker.#Copy & {
|
||||||
|
contents: source
|
||||||
|
"source": "go.mod"
|
||||||
|
dest: "go.mod"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Install CUE
|
||||||
|
bash.#Run & {
|
||||||
|
script: contents: #"""
|
||||||
|
export CUE_VERSION="$(grep cue ./go.mod | cut -d' ' -f2 | head -1 | sed -E 's/\.[[:digit:]]\.[[:alnum:]]+-[[:alnum:]]+$//')"
|
||||||
|
export CUE_TARBALL="cue_${CUE_VERSION}_linux_amd64.tar.gz"
|
||||||
|
echo "Installing cue version $CUE_VERSION"
|
||||||
|
curl -L "https://github.com/cue-lang/cue/releases/download/${CUE_VERSION}/${CUE_TARBALL}" | tar zxf - -C /usr/local/bin
|
||||||
|
cue version
|
||||||
|
"""#
|
||||||
|
},
|
||||||
|
|
||||||
|
// CACHE: copy only *.cue files
|
||||||
|
docker.#Copy & {
|
||||||
|
contents: source
|
||||||
|
include: ["*.cue"]
|
||||||
|
dest: "/cue"
|
||||||
|
},
|
||||||
|
|
||||||
|
// LINT
|
||||||
|
bash.#Run & {
|
||||||
|
workdir: "/cue"
|
||||||
|
script: contents: #"""
|
||||||
|
find . -name '*.cue' -not -path '*/cue.mod/*' -print | time xargs -t -n 1 -P 8 cue fmt -s
|
||||||
|
test -z "$(git status -s . | grep -e "^ M" | grep "\.cue" | cut -d ' ' -f3 | tee /dev/stderr)"
|
||||||
|
"""#
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ import (
|
|||||||
source: "golangci/golangci-lint:v\(version)"
|
source: "golangci/golangci-lint:v\(version)"
|
||||||
}
|
}
|
||||||
|
|
||||||
container: go.#Container & {
|
go.#Container & {
|
||||||
"source": source
|
"source": source
|
||||||
input: _image.output
|
input: _image.output
|
||||||
command: {
|
command: {
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
source: "tmknom/markdownlint:\(version)"
|
source: "tmknom/markdownlint:\(version)"
|
||||||
}
|
}
|
||||||
|
|
||||||
container: docker.#Run & {
|
docker.#Run & {
|
||||||
input: _image.output
|
input: _image.output
|
||||||
mounts: "source": {
|
mounts: "source": {
|
||||||
dest: "/src"
|
dest: "/src"
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
source: "koalaman/shellcheck-alpine:v\(version)"
|
source: "koalaman/shellcheck-alpine:v\(version)"
|
||||||
}
|
}
|
||||||
|
|
||||||
container: docker.#Run & {
|
docker.#Run & {
|
||||||
input: _image.output
|
input: _image.output
|
||||||
mounts: "source": {
|
mounts: "source": {
|
||||||
dest: "/src"
|
dest: "/src"
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
slug: /1205/container-images
|
|
||||||
displayed_sidebar: europa
|
|
||||||
---
|
|
||||||
|
|
||||||
# Building container images
|
|
||||||
|
|
||||||
You can use Dagger to build container images. Here's a simple example of a [Dockerfile](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) build:
|
|
||||||
|
|
||||||
```cue file=../tests/core-concepts/container-images/simple/with-dockerfile.cue
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building with CUE
|
|
||||||
|
|
||||||
`Dockerfile` files are easy to start, but you can also build images entirely in CUE. The following example produces the same image as above:
|
|
||||||
|
|
||||||
```cue file=../tests/core-concepts/container-images/simple/build.cue
|
|
||||||
```
|
|
||||||
|
|
||||||
## Automation
|
|
||||||
|
|
||||||
Building images in CUE gives you greater flexibility. For example, you can automate building multiple versions of an image, and deploy, all in Dagger:
|
|
||||||
|
|
||||||
```cue file=../tests/core-concepts/container-images/template/dagger.cue
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can deploy all versions:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
dagger do versions
|
|
||||||
```
|
|
||||||
|
|
||||||
Or just build a specific version, without pushing:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
dagger do versions 8.0 build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Multi-stage build
|
|
||||||
|
|
||||||
Another common pattern is [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds). This allows you to have heavier build images during the build process, and copy the built artifacts into a cleaner and lighter image to run in production.
|
|
||||||
|
|
||||||
```cue file=../tests/core-concepts/container-images/multi-stage/dagger.cue
|
|
||||||
```
|
|
140
docs/core-concepts/1221-action.md
Normal file
140
docs/core-concepts/1221-action.md
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
---
|
||||||
|
slug: /1221/action
|
||||||
|
displayed_sidebar: europa
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dagger Actions
|
||||||
|
|
||||||
|
Actions are the basic building block of the Dagger platform.
|
||||||
|
An action encapsulates an arbitrarily complex automation into a simple
|
||||||
|
software component that can be safely shared, and repeatably executed by any Dagger engine.
|
||||||
|
|
||||||
|
Actions can be executed directly with `dagger do`, or integrated as a component of a more complex action.
|
||||||
|
|
||||||
|
There are two types of actions: *core actions* and *composite actions*.
|
||||||
|
|
||||||
|
## Core Actions
|
||||||
|
|
||||||
|
Core Actions are primitives implemented by the Dagger Engine itself. They can be combined into higher-level composite actions. Their definitions can be imported in the `dagger.io/dagger/core` package.
|
||||||
|
|
||||||
|
To learn more about core actions, see [the core action reference](https://github.com/dagger/dagger/tree/main/pkg/dagger.io/dagger/core).
|
||||||
|
|
||||||
|
## Composite Actions
|
||||||
|
|
||||||
|
Composite Actions are actions made of other actions. Dagger supports arbitrary nesting of actions, so a composite action can be assembled from any combination of core and composite actions.
|
||||||
|
|
||||||
|
One consequence of arbitrary nesting is that Dagger doesn't need to distinguish between "pipelines" and "steps": everything is an action. Some actions are just more complex and powerful than others. This is a defining feature of Dagger.
|
||||||
|
|
||||||
|
## Lifecycle of an Action
|
||||||
|
|
||||||
|
A composite action's lifecycle has 4 stages:
|
||||||
|
|
||||||
|
1. Definition
|
||||||
|
2. Integration
|
||||||
|
3. Discovery
|
||||||
|
4. Execution
|
||||||
|
|
||||||
|
## Definition
|
||||||
|
|
||||||
|
A new action is *defined* in a declarative template called a [CUE definition](https://cuetorials.com/overview/foundations/#definitions). This definition describes the action's inputs, outputs, sub-actions, and the wiring between them.
|
||||||
|
|
||||||
|
Here is an example of a simple action definition:
|
||||||
|
|
||||||
|
```cue
|
||||||
|
package hello
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dagger.io/dagger/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Write a greeting to a file, and add it to a directory
|
||||||
|
#AddHello: {
|
||||||
|
// The input directory
|
||||||
|
dir: dagger.#FS
|
||||||
|
|
||||||
|
// The name of the person to greet
|
||||||
|
name: string | *"world"
|
||||||
|
|
||||||
|
write: core.#WriteFile & {
|
||||||
|
input: dir
|
||||||
|
path: "hello-\(name).txt"
|
||||||
|
contents: "hello, \(name)!"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The directory with greeting message added
|
||||||
|
result: write.output
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this action includes one sub-action: `core.#WriteFile`. An action can incorporate any number of sub-actions.
|
||||||
|
|
||||||
|
Also note the free-form structure: an action definition is not structured by a rigid schema. It is simply a CUE struct with fields of various types.
|
||||||
|
|
||||||
|
* "inputs" are simply fields which are not complete, and therefore can receive an external value at integration. For example, `dir` and `name` are inputs.
|
||||||
|
* "outputs" are simply fields which produce a value that can be referenced externally at integration. For example, `result` is an output.
|
||||||
|
* "sub-actions" are simply fields which contain another action definition. For example, `write` is a sub-action.
|
||||||
|
|
||||||
|
There are no constraints to an action's field names or types.
|
||||||
|
|
||||||
|
## Integration
|
||||||
|
|
||||||
|
Action definitions cannot be executed directly: they must be integrated into a plan.
|
||||||
|
|
||||||
|
A plan is an execution context for actions. It specifies:
|
||||||
|
|
||||||
|
* What actions to present to the end user
|
||||||
|
* Dependencies between those tasks, if any
|
||||||
|
* Interactions between the tasks and the client system, if any
|
||||||
|
|
||||||
|
Actions are integrated into a plan by *merging* their CUE definition into the plan's CUE definition.
|
||||||
|
|
||||||
|
Here is an example of a plan:
|
||||||
|
|
||||||
|
```cue
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dagger.io/dagger"
|
||||||
|
)
|
||||||
|
|
||||||
|
dagger.#Plan & {
|
||||||
|
// Say hello by writing to a file
|
||||||
|
actions: hello: #AddHello & {
|
||||||
|
dir: client.filesystem.".".read.contents
|
||||||
|
}
|
||||||
|
client: filesystem: ".": {
|
||||||
|
read: contents: dagger.#FS
|
||||||
|
write: contents: actions.hello.dir.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `#AddHello` was integrated *directly* into the plan, whereas `core.#WriteFile` was integrated *indirectly*, by virtue of being a sub-action of `#AddHello`.
|
||||||
|
|
||||||
|
To learn more about the structure of a plan, see [it all begins with a plan](./1202-plan).
|
||||||
|
|
||||||
|
## Discovery
|
||||||
|
|
||||||
|
Once integrated into a plan, actions can be discovered by end users, by using the familiar convention of usage messages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ dagger do --help
|
||||||
|
Execute a dagger action.
|
||||||
|
|
||||||
|
Available Actions:
|
||||||
|
hello Say hello by writing to a file
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
dagger do [OPTIONS] ACTION [SUBACTION...] [flags]
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
[...]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
Once the end user has discovered the action that they need, they can execute it with `dagger do`. For example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dagger do hello
|
||||||
|
```
|
54
docs/guides/1205-container-images.md
Normal file
54
docs/guides/1205-container-images.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
slug: /1205/container-images
|
||||||
|
displayed_sidebar: europa
|
||||||
|
---
|
||||||
|
|
||||||
|
# Building docker container images
|
||||||
|
|
||||||
|
You can use Dagger to build container images, either by executing a Dockerfile, or specifying the build steps natively in CUE. Which method to choose depends on the requirements of your project. You can mix and match builds from both methods in the same plan.
|
||||||
|
|
||||||
|
## Executing a Dockerfile
|
||||||
|
|
||||||
|
Dagger can natively load and execute Dockerfiles. This is recommended in cases where compatibility with existing Dockerfiles is more important than fully leveraging the power of CUE.
|
||||||
|
|
||||||
|
Here's a simple example of a [Dockerfile](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) build:
|
||||||
|
|
||||||
|
```cue file=../tests/core-concepts/container-images/simple/with-dockerfile.cue
|
||||||
|
```
|
||||||
|
|
||||||
|
## Specifying a build in CUE
|
||||||
|
|
||||||
|
You can specify your container build natively in CUE, using the official Docker package: `universe.dagger.io/docker`. This is recommended when you don't need to worry about Dockerfile compatibility, and want to take advantage of the full power of CUE and the Dagger APIs.
|
||||||
|
|
||||||
|
Native CUE builds have the same backend as Dockerfile builds, so all the same features are available. Since CUE is a more powerful language than the Dockerfile syntax, every Dockerfile can be ported to an equivalent CUE configuration, but the opposite is not true. The following example produces the same image as above.
|
||||||
|
|
||||||
|
```cue file=../tests/core-concepts/container-images/simple/build.cue
|
||||||
|
```
|
||||||
|
|
||||||
|
Because this build configuration is pure CUE, it can leverage the full power of Dagger's composition model.
|
||||||
|
|
||||||
|
## Automation
|
||||||
|
|
||||||
|
Building images in CUE gives you greater flexibility. For example, you can automate building multiple versions of an image, and deploy, all in Dagger:
|
||||||
|
|
||||||
|
```cue file=../tests/core-concepts/container-images/template/dagger.cue
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can deploy all versions:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dagger do versions
|
||||||
|
```
|
||||||
|
|
||||||
|
Or just build a specific version, without pushing:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dagger do versions 8.0 build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multi-stage build
|
||||||
|
|
||||||
|
Another common pattern is [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds). This allows you to have heavier build images during the build process, and copy the built artifacts into a cleaner and lighter image to run in production.
|
||||||
|
|
||||||
|
```cue file=../tests/core-concepts/container-images/multi-stage/dagger.cue
|
||||||
|
```
|
@ -5,16 +5,23 @@ import (
|
|||||||
"universe.dagger.io/docker"
|
"universe.dagger.io/docker"
|
||||||
)
|
)
|
||||||
|
|
||||||
dagger.#Plan & {
|
// This action builds a docker image from a python app.
|
||||||
client: filesystem: "./src": read: contents: dagger.#FS
|
// Build steps are defined in native CUE.
|
||||||
|
#PythonBuild: {
|
||||||
|
// Source code of the Python application
|
||||||
|
app: dagger.#FS
|
||||||
|
|
||||||
actions: build: docker.#Build & {
|
// Container image
|
||||||
|
image: _build.output
|
||||||
|
|
||||||
|
// Build steps
|
||||||
|
_build: docker.#Build & {
|
||||||
steps: [
|
steps: [
|
||||||
docker.#Pull & {
|
docker.#Pull & {
|
||||||
source: "python:3.9"
|
source: "python:3.9"
|
||||||
},
|
},
|
||||||
docker.#Copy & {
|
docker.#Copy & {
|
||||||
contents: client.filesystem."./src".read.contents
|
contents: app
|
||||||
dest: "/app"
|
dest: "/app"
|
||||||
},
|
},
|
||||||
docker.#Run & {
|
docker.#Run & {
|
||||||
@ -29,3 +36,12 @@ dagger.#Plan & {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Example usage in a plan
|
||||||
|
dagger.#Plan & {
|
||||||
|
client: filesystem: "./src": read: contents: dagger.#FS
|
||||||
|
|
||||||
|
actions: build: #PythonBuild & {
|
||||||
|
app: client.filesystem."./src".read.contents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,21 +5,22 @@ import (
|
|||||||
"universe.dagger.io/docker"
|
"universe.dagger.io/docker"
|
||||||
)
|
)
|
||||||
|
|
||||||
dagger.#Plan & {
|
// This action builds a docker image from a python app.
|
||||||
client: filesystem: "./src": read: contents: dagger.#FS
|
// Build steps are defined in an inline Dockerfile.
|
||||||
|
#PythonBuild: docker.#Dockerfile & {
|
||||||
actions: build: docker.#Dockerfile & {
|
dockerfile: contents: """
|
||||||
// This is the context.
|
|
||||||
source: client.filesystem."./src".read.contents
|
|
||||||
|
|
||||||
// Default is to look for a Dockerfile in the context,
|
|
||||||
// but let's declare it here.
|
|
||||||
dockerfile: contents: #"""
|
|
||||||
FROM python:3.9
|
FROM python:3.9
|
||||||
COPY . /app
|
COPY . /app
|
||||||
RUN pip install -r /app/requirements.txt
|
RUN pip install -r /app/requirements.txt
|
||||||
CMD python /app/app.py
|
CMD python /app/app.py
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
"""#
|
// Example usage in a plan
|
||||||
|
dagger.#Plan & {
|
||||||
|
client: filesystem: "./src": read: contents: dagger.#FS
|
||||||
|
|
||||||
|
actions: build: #PythonBuild & {
|
||||||
|
source: client.filesystem."./src".read.contents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
go.mod
6
go.mod
@ -31,10 +31,10 @@ require (
|
|||||||
github.com/tonistiigi/fsutil v0.0.0-20220315205639-9ed612626da3
|
github.com/tonistiigi/fsutil v0.0.0-20220315205639-9ed612626da3
|
||||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
||||||
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f
|
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f
|
||||||
go.opentelemetry.io/otel v1.6.1
|
go.opentelemetry.io/otel v1.6.2
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.6.1
|
go.opentelemetry.io/otel/exporters/jaeger v1.6.1
|
||||||
go.opentelemetry.io/otel/sdk v1.6.1
|
go.opentelemetry.io/otel/sdk v1.6.2
|
||||||
go.opentelemetry.io/otel/trace v1.6.1
|
go.opentelemetry.io/otel/trace v1.6.2
|
||||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57
|
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||||
|
9
go.sum
9
go.sum
@ -1498,8 +1498,9 @@ go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzox
|
|||||||
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
|
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
|
||||||
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
|
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
|
||||||
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
|
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
|
||||||
go.opentelemetry.io/otel v1.6.1 h1:6r1YrcTenBvYa1x491d0GGpTVBsNECmrc/K6b+zDeis=
|
|
||||||
go.opentelemetry.io/otel v1.6.1/go.mod h1:blzUabWHkX6LJewxvadmzafgh/wnvBSDBdOuwkAtrWQ=
|
go.opentelemetry.io/otel v1.6.1/go.mod h1:blzUabWHkX6LJewxvadmzafgh/wnvBSDBdOuwkAtrWQ=
|
||||||
|
go.opentelemetry.io/otel v1.6.2 h1:iLrj1F5ydCSVc4CGjBX2ou/QRav3C8xHjHlVoch6g4w=
|
||||||
|
go.opentelemetry.io/otel v1.6.2/go.mod h1:MUBZHaB2cm6CahEBHQPq9Anos7IXynP/noVpjsxQTSc=
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI=
|
go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI=
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.6.1 h1:7xuwXr3qUWq48Chyuq+VvomV3KjXZLd5seQwg83s/sU=
|
go.opentelemetry.io/otel/exporters/jaeger v1.6.1 h1:7xuwXr3qUWq48Chyuq+VvomV3KjXZLd5seQwg83s/sU=
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.6.1/go.mod h1:Cu6mKJ+LLTPuOBX830xM4wVKIsVpHSXa50uN7aAxraQ=
|
go.opentelemetry.io/otel/exporters/jaeger v1.6.1/go.mod h1:Cu6mKJ+LLTPuOBX830xM4wVKIsVpHSXa50uN7aAxraQ=
|
||||||
@ -1521,16 +1522,18 @@ go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa
|
|||||||
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
|
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
|
||||||
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
|
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
|
||||||
go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE=
|
go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE=
|
||||||
go.opentelemetry.io/otel/sdk v1.6.1 h1:ZmcNyMhcuAYIb/Nr6QhBPTMopMTbov/47wHt1gibkoY=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.6.1/go.mod h1:IVYrddmFZ+eJqu2k38qD3WezFR2pymCzm8tdxyh3R4E=
|
go.opentelemetry.io/otel/sdk v1.6.1/go.mod h1:IVYrddmFZ+eJqu2k38qD3WezFR2pymCzm8tdxyh3R4E=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.6.2 h1:wxY+YrfpGJfjxtm7SFBMJp9APDMZjDG+ErZOs/wkubg=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.6.2/go.mod h1:M2r4VCm1Yurk4E+fWtP2p+QzFDHMFEqhGdbtQ7zRf+k=
|
||||||
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
|
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
|
||||||
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
|
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
|
||||||
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
|
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
|
||||||
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
|
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
|
||||||
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
|
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
|
||||||
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
|
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
|
||||||
go.opentelemetry.io/otel/trace v1.6.1 h1:f8c93l5tboBYZna1nWk0W9DYyMzJXDWdZcJZ0Kb400U=
|
|
||||||
go.opentelemetry.io/otel/trace v1.6.1/go.mod h1:RkFRM1m0puWIq10oxImnGEduNBzxiN7TXluRBtE+5j0=
|
go.opentelemetry.io/otel/trace v1.6.1/go.mod h1:RkFRM1m0puWIq10oxImnGEduNBzxiN7TXluRBtE+5j0=
|
||||||
|
go.opentelemetry.io/otel/trace v1.6.2 h1:oY7i1k6XD/ozlGo7ASy+H1UdkNcj9cPfuklaYSXtoFk=
|
||||||
|
go.opentelemetry.io/otel/trace v1.6.2/go.mod h1:RMqfw8Mclba1p7sXDmEDBvrB8jw65F6GOoN1fyyXTzk=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
|
go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
|
||||||
go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c=
|
go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c=
|
||||||
|
@ -95,15 +95,22 @@ module.exports = {
|
|||||||
title: 'Core Concepts',
|
title: 'Core Concepts',
|
||||||
},
|
},
|
||||||
items: [
|
items: [
|
||||||
|
"core-concepts/action",
|
||||||
"core-concepts/plan",
|
"core-concepts/plan",
|
||||||
"core-concepts/client",
|
"core-concepts/client",
|
||||||
"core-concepts/secrets",
|
"core-concepts/secrets",
|
||||||
"core-concepts/container-images",
|
|
||||||
"core-concepts/what-is-cue",
|
"core-concepts/what-is-cue",
|
||||||
"core-concepts/dagger-cue",
|
"core-concepts/dagger-cue",
|
||||||
"core-concepts/cli-telemetry",
|
"core-concepts/cli-telemetry",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
label: "Guides",
|
||||||
|
collapsible: false,
|
||||||
|
collapsed: false,
|
||||||
|
items: ["guides/container-images"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "category",
|
type: "category",
|
||||||
label: "Use Cases",
|
label: "Use Cases",
|
||||||
|
Reference in New Issue
Block a user