Merge pull request #1056 from aluzzardi/docker-load
Support loading artifacts into a Docker Engine
This commit is contained in:
commit
16b14524d5
@ -144,6 +144,16 @@ _No input._
|
||||
|
||||
_No output._
|
||||
|
||||
## op.#SaveImage
|
||||
|
||||
### op.#SaveImage Inputs
|
||||
|
||||
_No input._
|
||||
|
||||
### op.#SaveImage Outputs
|
||||
|
||||
_No output._
|
||||
|
||||
## op.#Subdir
|
||||
|
||||
### op.#Subdir Inputs
|
||||
|
@ -31,15 +31,29 @@ A container image that can run any docker command
|
||||
|
||||
### docker.#Command Inputs
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*command* | `string` |Command to execute |
|
||||
|*registries* | `[]` |Image registries |
|
||||
_No input._
|
||||
|
||||
### docker.#Command Outputs
|
||||
|
||||
_No output._
|
||||
|
||||
## docker.#Load
|
||||
|
||||
Load a docker image into a docker engine
|
||||
|
||||
### docker.#Load Inputs
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*tag* | `string` |Name and optionally a tag in the 'name:tag' format |
|
||||
|*source* | `dagger.#Artifact` |Image source |
|
||||
|
||||
### docker.#Load Outputs
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*id* | `string` |Image ID |
|
||||
|
||||
## docker.#Pull
|
||||
|
||||
Pull a docker container
|
||||
@ -79,9 +93,7 @@ Push a docker image to a remote registry
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*ref* | `string` |Image reference (e.g: nginx:alpine) |
|
||||
|*run.command* | `"""\n # Run detach container\n OPTS=""\n \n if [ ! -z "$CONTAINER_NAME" ]; then\n \tOPTS="$OPTS --name $CONTAINER_NAME"\n fi\n \n if [ ! -z "$CONTAINER_PORTS" ]; then\n \tOPTS="$OPTS -p $CONTAINER_PORTS"\n fi\n \n docker container run -d $OPTS "$IMAGE_REF"\n """` |Command to execute |
|
||||
|*run.env.IMAGE_REF* | `string` |- |
|
||||
|*run.registries* | `[]` |Image registries |
|
||||
|
||||
### docker.#Run Outputs
|
||||
|
||||
|
@ -14,14 +14,10 @@ import "alpha.dagger.io/docker/compose"
|
||||
|
||||
### compose.#App Inputs
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*name* | `*"source" \| string` |App name (use as COMPOSE_PROJECT_NAME) |
|
||||
|*registries* | `[]` |Image registries |
|
||||
|*run.command* | `"""\n if [ -n "$DOCKER_HOSTNAME" ]; then\n \tssh -i /key -fNT -o "StreamLocalBindUnlink=yes" -L "$(pwd)"/docker.sock:/var/run/docker.sock -p "$DOCKER_PORT" "$DOCKER_USERNAME"@"$DOCKER_HOSTNAME"\n \texport DOCKER_HOST="unix://$(pwd)/docker.sock"\n fi\n \n # Extend session duration\n echo "Host *\\nServerAliveInterval 240" \>\> "$HOME"/.ssh/config\n chmod 600 "$HOME"/.ssh/config\n \n # Move compose\n if [ -d "$SOURCE_DIR" ]; then\n \tif [ -f docker-compose.yaml ]; then\n \t\tcp docker-compose.yaml "$SOURCE_DIR"/docker-compose.yaml\n \tfi\n \tcd "$SOURCE_DIR"\n fi\n \n docker-compose build\n docker-compose up -d\n """` |Command to execute |
|
||||
|*run.env.COMPOSE_PROJECT_NAME* | `*"source" \| string` |- |
|
||||
|*run.package."docker-compose"* | `true` |- |
|
||||
|*run.registries* | `[]` |Image registries |
|
||||
| Name | Type | Description |
|
||||
| ------------- |:-------------: |:-------------: |
|
||||
|*name* | `*"source" \| string` |App name (use as COMPOSE_PROJECT_NAME) |
|
||||
|*registries* | `[]` |Image registries |
|
||||
|
||||
### compose.#App Outputs
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/url"
|
||||
@ -261,6 +262,8 @@ func (p *Pipeline) doOp(ctx context.Context, op *compiler.Value, st llb.State) (
|
||||
return p.FetchContainer(ctx, op, st)
|
||||
case "push-container":
|
||||
return p.PushContainer(ctx, op, st)
|
||||
case "save-image":
|
||||
return p.SaveImage(ctx, op, st)
|
||||
case "fetch-git":
|
||||
return p.FetchGit(ctx, op, st)
|
||||
case "fetch-http":
|
||||
@ -872,6 +875,63 @@ func (p *Pipeline) PushContainer(ctx context.Context, op *compiler.Value, st llb
|
||||
return st, err
|
||||
}
|
||||
|
||||
func (p *Pipeline) SaveImage(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||
tag, err := op.Lookup("tag").String()
|
||||
if err != nil {
|
||||
return st, err
|
||||
}
|
||||
|
||||
dest, err := op.Lookup("dest").String()
|
||||
if err != nil {
|
||||
return st, err
|
||||
}
|
||||
|
||||
pipeR, pipeW := io.Pipe()
|
||||
var (
|
||||
errCh = make(chan error)
|
||||
image []byte
|
||||
)
|
||||
go func() {
|
||||
var err error
|
||||
|
||||
image, err = io.ReadAll(pipeR)
|
||||
errCh <- err
|
||||
}()
|
||||
|
||||
resp, err := p.s.Export(ctx, p.State(), &p.image, bk.ExportEntry{
|
||||
Type: bk.ExporterDocker,
|
||||
Attrs: map[string]string{
|
||||
"name": tag,
|
||||
},
|
||||
Output: func(_ map[string]string) (io.WriteCloser, error) {
|
||||
return pipeW, nil
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return st, err
|
||||
}
|
||||
|
||||
if err := <-errCh; err != nil {
|
||||
return st, err
|
||||
}
|
||||
|
||||
if id, ok := resp.ExporterResponse["containerimage.config.digest"]; ok {
|
||||
st = st.File(
|
||||
llb.Mkdir("/dagger", fs.FileMode(0755)),
|
||||
llb.WithCustomName(p.vertexNamef("Mkdir /dagger")),
|
||||
).File(
|
||||
llb.Mkfile("/dagger/image_id", fs.FileMode(0644), []byte(id)),
|
||||
llb.WithCustomName(p.vertexNamef("Storing image id to /dagger/image_id")),
|
||||
)
|
||||
}
|
||||
|
||||
return st.File(
|
||||
llb.Mkfile(dest, 0644, image),
|
||||
llb.WithCustomName(p.vertexNamef("SaveImage %s", dest)),
|
||||
), nil
|
||||
}
|
||||
|
||||
func getSecretID(secretField *compiler.Value) (string, error) {
|
||||
if !secretField.HasAttr("secret") {
|
||||
return "", fmt.Errorf("invalid secret %q: not a secret", secretField.Path().String())
|
||||
|
2
stdlib/.dagger/env/docker-load/.gitignore
vendored
Normal file
2
stdlib/.dagger/env/docker-load/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# dagger state
|
||||
state/**
|
30
stdlib/.dagger/env/docker-load/values.yaml
vendored
Normal file
30
stdlib/.dagger/env/docker-load/values.yaml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
plan:
|
||||
package: ./docker/tests/load
|
||||
name: docker-load
|
||||
inputs:
|
||||
dockersocket:
|
||||
socket:
|
||||
unix: /var/run/docker.sock
|
||||
source:
|
||||
dir:
|
||||
path: ./docker/tests/load/testdata
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1gxwmtwahzwdmrskhf90ppwlnze30lgpm056kuesrxzeuyclrwvpsupwtpk
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzZCt6S3VGQkM4ZU9TamhQ
|
||||
c2J0RDZpdzNQZUJ6V1BBdHh3M1NhTmJLeXpFCldaOVNUYVhWQW5ma3JGUk9XZWZ2
|
||||
YjZIM0tMUGRoSk1QYTFkalA4S2N3UzAKLS0tIFhMeXMvaGM4UFllYWFCNWVUZFd5
|
||||
U09jNHNlK094NGoyZnRlSk56T1N6K1EKJs5D3S2zPWNrGCyLWDDjq7Iif0m2JoL6
|
||||
gqEjofnPSD7SjgfNKIpeOWcQ1sI7wmI4GGgaTpdhd431XxOn/fU44w==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2021-10-12T22:18:14Z"
|
||||
mac: ENC[AES256_GCM,data:HjlY0FzB5hsg/VfyBbVTNWDCYV41lhPeyHOVrMdRWiOKJnV1aKGV1826fMXKcmgJK39kovcEXaXmVYOv3qtpDTlIMcOdoEflbDY/fhZmaDxxNq6QSkYfmadO84YWvS1FyouCPVZzRDe9tBdNyIT5cCx8CrgZ5bebh9aNem3lqRs=,iv:juMn1S06I5mZP8fWytn2eUkOvjNQepn6MAzDWvLxrWM=,tag:0BxrbK6EaoB44RgUHD+dpQ==,type:str]
|
||||
pgp: []
|
||||
encrypted_suffix: secret
|
||||
version: 3.7.1
|
@ -81,6 +81,12 @@ package op
|
||||
ref: string
|
||||
}
|
||||
|
||||
#SaveImage: {
|
||||
do: "save-image"
|
||||
tag: string
|
||||
dest: string
|
||||
}
|
||||
|
||||
#FetchGit: {
|
||||
do: "fetch-git"
|
||||
remote: string
|
||||
|
@ -31,11 +31,11 @@ import (
|
||||
}
|
||||
|
||||
// Command to execute
|
||||
command: string @dagger(input)
|
||||
command: string
|
||||
|
||||
// Environment variables shared by all commands
|
||||
env: {
|
||||
[string]: string @dagger(input)
|
||||
[string]: string
|
||||
}
|
||||
|
||||
// Mount content from other artifacts
|
||||
@ -44,17 +44,17 @@ import (
|
||||
from: dagger.#Artifact
|
||||
} | {
|
||||
secret: dagger.#Secret
|
||||
} @dagger(input)
|
||||
}
|
||||
}
|
||||
|
||||
// Mount persistent cache directories
|
||||
cache: {
|
||||
[string]: true @dagger(input)
|
||||
[string]: true
|
||||
}
|
||||
|
||||
// Mount temporary directories
|
||||
tmpfs: {
|
||||
[string]: true @dagger(input)
|
||||
[string]: true
|
||||
}
|
||||
|
||||
// Mount docker socket
|
||||
@ -62,7 +62,7 @@ import (
|
||||
|
||||
// Additional packages to install
|
||||
package: {
|
||||
[string]: true | false | string @dagger(input)
|
||||
[string]: true | false | string
|
||||
}
|
||||
|
||||
// Image registries
|
||||
@ -70,7 +70,7 @@ import (
|
||||
target?: string
|
||||
username: string
|
||||
secret: dagger.#Secret
|
||||
}] @dagger(input)
|
||||
}]
|
||||
|
||||
// Copy contents from other artifacts
|
||||
copy: [string]: from: dagger.#Artifact
|
||||
@ -98,7 +98,7 @@ import (
|
||||
ssh-add /key > /dev/null
|
||||
if [ "$?" != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -z $FINGERPRINT ]]; then
|
||||
@ -131,7 +131,7 @@ import (
|
||||
for registry in registries {
|
||||
op.#Exec & {
|
||||
args: ["/bin/bash", "-c", #"""
|
||||
echo "$TARGER_HOST" | docker login --username "$DOCKER_USERNAME" --password-stdin "$(cat /password)"
|
||||
echo "$TARGER_HOST" | docker login --username "$DOCKER_USERNAME" --password-stdin "$(cat /password)"
|
||||
"""#,
|
||||
]
|
||||
env: {
|
||||
|
@ -101,6 +101,74 @@ import (
|
||||
} & dagger.#Output
|
||||
}
|
||||
|
||||
// Load a docker image into a docker engine
|
||||
#Load: {
|
||||
// Connect to a remote SSH server
|
||||
ssh?: {
|
||||
// ssh host
|
||||
host: dagger.#Input & {string}
|
||||
|
||||
// ssh user
|
||||
user: dagger.#Input & {string}
|
||||
|
||||
// ssh port
|
||||
port: dagger.#Input & {*22 | int}
|
||||
|
||||
// private key
|
||||
key: dagger.#Input & {dagger.#Secret}
|
||||
|
||||
// fingerprint
|
||||
fingerprint?: dagger.#Input & {string}
|
||||
|
||||
// ssh key passphrase
|
||||
keyPassphrase?: dagger.#Input & {dagger.#Secret}
|
||||
}
|
||||
|
||||
// Mount local docker socket
|
||||
socket?: dagger.#Stream & dagger.#Input
|
||||
|
||||
// Name and optionally a tag in the 'name:tag' format
|
||||
tag: dagger.#Input & {string}
|
||||
|
||||
// Image source
|
||||
source: dagger.#Input & {dagger.#Artifact}
|
||||
|
||||
save: #up: [
|
||||
op.#Load & {from: source},
|
||||
|
||||
op.#SaveImage & {
|
||||
"tag": tag
|
||||
dest: "/image.tar"
|
||||
},
|
||||
]
|
||||
|
||||
load: #Command & {
|
||||
if ssh != _|_ {
|
||||
"ssh": ssh
|
||||
}
|
||||
if socket != _|_ {
|
||||
"socket": socket
|
||||
}
|
||||
|
||||
copy: "/src": from: save
|
||||
|
||||
command: "docker load -i /src/image.tar"
|
||||
}
|
||||
|
||||
// Image ID
|
||||
id: {
|
||||
string
|
||||
|
||||
#up: [
|
||||
op.#Load & {from: save},
|
||||
|
||||
op.#Export & {
|
||||
source: "/dagger/image_id"
|
||||
},
|
||||
]
|
||||
} & dagger.#Output
|
||||
}
|
||||
|
||||
#Run: {
|
||||
// Connect to a remote SSH server
|
||||
ssh?: {
|
||||
|
32
stdlib/docker/tests/load/load.cue
Normal file
32
stdlib/docker/tests/load/load.cue
Normal file
@ -0,0 +1,32 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"alpha.dagger.io/dagger"
|
||||
"alpha.dagger.io/random"
|
||||
)
|
||||
|
||||
dockersocket: dagger.#Stream & dagger.#Input
|
||||
|
||||
source: dagger.#Artifact & dagger.#Input
|
||||
|
||||
TestLoad: {
|
||||
suffix: random.#String & {
|
||||
seed: ""
|
||||
}
|
||||
|
||||
image: #Build & {
|
||||
"source": source
|
||||
}
|
||||
|
||||
load: #Load & {
|
||||
tag: "daggerci-image-load-\(suffix.out)"
|
||||
source: image
|
||||
socket: dockersocket
|
||||
}
|
||||
|
||||
run: #Run & {
|
||||
name: "daggerci-container-load-\(suffix.out)"
|
||||
ref: load.id
|
||||
socket: dockersocket
|
||||
}
|
||||
}
|
2
stdlib/docker/tests/load/testdata/Dockerfile
vendored
Normal file
2
stdlib/docker/tests/load/testdata/Dockerfile
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
FROM alpine
|
||||
RUN echo test >> /test.txt
|
@ -126,6 +126,10 @@ setup() {
|
||||
assert_failure
|
||||
}
|
||||
|
||||
@test "docker load" {
|
||||
dagger -e docker-load up
|
||||
}
|
||||
|
||||
@test "docker compose" {
|
||||
dagger -e docker-compose up
|
||||
}
|
||||
@ -177,7 +181,7 @@ setup() {
|
||||
}
|
||||
|
||||
@test "google cloud: gke" {
|
||||
dagger -e google-gke up
|
||||
dagger -e google-gke up
|
||||
}
|
||||
|
||||
@test "google cloud: secretmanager" {
|
||||
|
Reference in New Issue
Block a user