Split dockerfile generation in multiple steps
Signed-off-by: Dimitris Karakasilis <dimitris@karakasilis.me>
This commit is contained in:
33
Dockerfile
33
Dockerfile
@@ -1,26 +1,19 @@
|
|||||||
ARG GO_VERSION=1.20-alpine3.18
|
|
||||||
FROM golang:$GO_VERSION AS builder
|
|
||||||
|
|
||||||
WORKDIR /build
|
FROM ubuntu:latest as base
|
||||||
COPY . .
|
FROM busybox as builder
|
||||||
|
|
||||||
ENV CGO_ENABLED=0
|
COPY --from=base . /rootfs
|
||||||
RUN go mod download
|
|
||||||
# Set arg/env after go mod download, otherwise we invalidate the cached layers due to the commit changing easily
|
|
||||||
ARG ENKI_VERSION
|
|
||||||
ARG ENKI_COMMIT
|
|
||||||
ENV ENKI_VERSION=${ENKI_VERSION}
|
|
||||||
ENV ENKI_COMMIT=${ENKI_COMMIT}
|
|
||||||
RUN go build \
|
|
||||||
-ldflags "-w -s \
|
|
||||||
-X github.com/kairos-io/enki/internal/version.version=$ENKI_VERSION \
|
|
||||||
-X github.com/kairos-io/enki/internal/version.gitCommit=$ENKI_COMMIT" \
|
|
||||||
-o /enki
|
|
||||||
|
|
||||||
FROM gcr.io/kaniko-project/executor:latest
|
FROM rootfs
|
||||||
|
# Additional os specific things
|
||||||
|
|
||||||
COPY --from=builder /enki /enki
|
RUN echo "nameserver 8.8.8.8" > /rootfs/etc/resolv.conf
|
||||||
|
RUN cat /rootfs/etc/resolv.conf
|
||||||
|
|
||||||
ENTRYPOINT ["/enki"]
|
FROM scratch as rootfs
|
||||||
|
|
||||||
|
COPY --from=builder /rootfs/ .
|
||||||
|
|
||||||
|
FROM rootfs
|
||||||
|
# Additional os specific things
|
||||||
|
|
||||||
CMD ["convert"]
|
|
||||||
|
@@ -16,9 +16,9 @@ func NewDockerfileCmd() *cobra.Command {
|
|||||||
Long: "Create a dockerfile that builds a Kairos image from the provided one\n\n" +
|
Long: "Create a dockerfile that builds a Kairos image from the provided one\n\n" +
|
||||||
"The base image can be specified either as a directory where the image has been extracted or as an image uri.\n" +
|
"The base image can be specified either as a directory where the image has been extracted or as an image uri.\n" +
|
||||||
"This is best effort. Enki will try to detect the distribution and add the necessary bits to convert it to a Kairos image",
|
"This is best effort. Enki will try to detect the distribution and add the necessary bits to convert it to a Kairos image",
|
||||||
Args: cobra.ExactArgs(3),
|
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return CheckRoot() // TODO: Do we need root?
|
//return CheckRoot() // TODO: Do we need root?
|
||||||
|
return nil
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
// Set this after parsing of the flags, so it fails on parsing and prints usage properly
|
// Set this after parsing of the flags, so it fails on parsing and prints usage properly
|
||||||
|
@@ -55,9 +55,10 @@ func NewConverterAction(rootfsPath, resultPath, imageName string, runner Runner)
|
|||||||
// E.g.
|
// E.g.
|
||||||
// CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o build/enki && docker run -it -e PATH=/kaniko -v /tmp -v /home/dimitris/workspace/kairos/osbuilder/tmp/rootfs/:/context -v "$PWD/build/enki":/enki -v $PWD:/build --rm --entrypoint "/enki" gcr.io/kaniko-project/executor:latest convert /context
|
// CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o build/enki && docker run -it -e PATH=/kaniko -v /tmp -v /home/dimitris/workspace/kairos/osbuilder/tmp/rootfs/:/context -v "$PWD/build/enki":/enki -v $PWD:/build --rm --entrypoint "/enki" gcr.io/kaniko-project/executor:latest convert /context
|
||||||
func (ca *ConverterAction) Run() (err error) {
|
func (ca *ConverterAction) Run() (err error) {
|
||||||
dockerfile, err := ca.createDockerfile()
|
da := NewDockerfileAction(ca.rootFSPath, "")
|
||||||
|
dockerfile, err := da.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
defer os.Remove(dockerfile)
|
defer os.Remove(dockerfile)
|
||||||
|
|
||||||
@@ -75,40 +76,6 @@ func (ca *ConverterAction) Run() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *ConverterAction) createDockerfile() (string, error) {
|
|
||||||
f, err := os.CreateTemp("", "")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
// write data to the temporary file
|
|
||||||
data := []byte(`
|
|
||||||
FROM busybox as builder
|
|
||||||
RUN mkdir /rootfs
|
|
||||||
COPY . /rootfs/.
|
|
||||||
|
|
||||||
RUN echo "nameserver 8.8.8.8" > /rootfs/etc/resolv.conf
|
|
||||||
RUN cat /rootfs/etc/resolv.conf
|
|
||||||
|
|
||||||
FROM scratch as rootfs
|
|
||||||
|
|
||||||
COPY --from=builder /rootfs/ .
|
|
||||||
|
|
||||||
FROM rootfs
|
|
||||||
|
|
||||||
# TODO: Do more clever things
|
|
||||||
RUN apt-get update && apt-get install -y curl
|
|
||||||
`)
|
|
||||||
|
|
||||||
if _, err := f.Write(data); err != nil {
|
|
||||||
os.Remove(f.Name())
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/GoogleContainerTools/kaniko/issues/1007
|
// https://github.com/GoogleContainerTools/kaniko/issues/1007
|
||||||
// Create a .dockerignore in the rootfs directory to skip these:
|
// Create a .dockerignore in the rootfs directory to skip these:
|
||||||
// https://github.com/GoogleContainerTools/kaniko/pull/1724/files#diff-1e90758e2fb0f26bdbfe7a40aafc4b4796cbf808842703e52e16c1f36b8da7dcR89
|
// https://github.com/GoogleContainerTools/kaniko/pull/1724/files#diff-1e90758e2fb0f26bdbfe7a40aafc4b4796cbf808842703e52e16c1f36b8da7dcR89
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// ConverterAction is the action that converts a non-kairos image to a Kairos one.
|
// ConverterAction is the action that converts a non-kairos image to a Kairos one.
|
||||||
// The conversion happens in a best-effort manner. It's not guaranteed that
|
// The conversion happens in a best-effort manner. It's not guaranteed that
|
||||||
@@ -21,9 +24,72 @@ func NewDockerfileAction(rootfsPath, baseImageURI string) *DockerfileAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *DockerfileAction) Run() (dockerfile string, err error) {
|
func (a *DockerfileAction) Run() (dockerfile string, err error) {
|
||||||
if a.rootFSPath != "" && a.baseImageURI != "" {
|
if err := a.Validate(); err != nil {
|
||||||
return "", errors.New("only one of 'rootfs-dir' and 'base-image-uri' should be defined")
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
dockerfile = ""
|
||||||
|
dockerfile += a.baseImageSection()
|
||||||
|
dockerfile += a.dnsSection()
|
||||||
|
dockerfile += a.footerSection()
|
||||||
|
dockerfile += a.osSpecificSection()
|
||||||
|
|
||||||
|
return dockerfile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DockerfileAction) baseImageSection() string {
|
||||||
|
result := ""
|
||||||
|
if a.baseImageURI != "" {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
FROM %s as base
|
||||||
|
FROM busybox as builder
|
||||||
|
|
||||||
|
COPY --from=base . /rootfs
|
||||||
|
|
||||||
|
FROM rootfs
|
||||||
|
# Additional os specific things
|
||||||
|
`, a.baseImageURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = fmt.Sprintf(`
|
||||||
|
FROM busybox as builder
|
||||||
|
RUN mkdir /rootfs
|
||||||
|
COPY %s /rootfs/.
|
||||||
|
|
||||||
|
FROM rootfs
|
||||||
|
# Additional os specific things
|
||||||
|
`, a.rootFSPath)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DockerfileAction) dnsSection() string {
|
||||||
|
return `
|
||||||
|
RUN echo "nameserver 8.8.8.8" > /rootfs/etc/resolv.conf
|
||||||
|
RUN cat /rootfs/etc/resolv.conf
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DockerfileAction) footerSection() string {
|
||||||
|
return `
|
||||||
|
FROM scratch as rootfs
|
||||||
|
|
||||||
|
COPY --from=builder /rootfs/ .
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DockerfileAction) osSpecificSection() string {
|
||||||
|
return `
|
||||||
|
FROM rootfs
|
||||||
|
# Additional os specific things
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DockerfileAction) Validate() error {
|
||||||
|
if a.rootFSPath != "" && a.baseImageURI != "" ||
|
||||||
|
a.rootFSPath == "" && a.baseImageURI == "" {
|
||||||
|
return errors.New("exactly one of 'rootfs-dir' and 'base-image-uri' should be defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user