Skip to content

Commit

Permalink
Use minimum distroless base image (#261)
Browse files Browse the repository at this point in the history
* Use minimum distroless base image

#228 was reverted due to
deployment to Fly requires `bash`. The bash script is replaced with a Go binary
(`uptermd-fly`). Dockerfile.upterm is adjusted to accomondate for Fly deployment and
self-hosting with different build targets.

* Use Docker GitHub Actions
  • Loading branch information
owenthereal committed May 21, 2024
1 parent 1b54c1d commit 1846c3a
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 132 deletions.
11 changes: 4 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ jobs:
- name: Vet
run: make vet
docker:
name: Docker
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
- name: Docker
run: make docker_build
name: Docker
needs: [build, test, vet]
uses: ./.github/workflows/docker.yaml
secrets: inherit
43 changes: 43 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Docker
on:
workflow_call:
workflow_dispatch:
jobs:
docker_build:
name: Build Docker image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Docker QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: amd64,arm64
- name: Login to ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/owenthereal/upterm/uptermd
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha,prefix=,suffix=,format=long
- name: Docker build and push
uses: docker/build-push-action@v5
with:
push: ${{ startsWith(github.ref, 'refs/tags/v') }}
pull: true
file: Dockerfile.uptermd
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: |
type=gha
cache-to: |
type=gha,mode=max
15 changes: 7 additions & 8 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ on:
push:
tags: 'v*'
jobs:
release:
docker:
name: Docker
uses: ./.github/workflows/docker.yaml
secrets: inherit
gorelease:
name: Upload releases
runs-on: ubuntu-latest
needs: [docker]
steps:
- uses: actions/checkout@v4
- name: Set up Go
Expand All @@ -20,16 +25,10 @@ jobs:
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- name: Docker push on master
run: |
# Build & publish on master
echo "${{ secrets.GH_TOKEN }}" | docker login ghcr.io -u USERNAME --password-stdin
TAG=${GITHUB_REF_NAME} make docker_push
TAG=latest make docker_push
deploy:
name: Deploy app
runs-on: ubuntu-latest
needs: [release]
needs: [gorelease]
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
Expand Down
37 changes: 25 additions & 12 deletions Dockerfile.uptermd
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
FROM golang:alpine as builder
# syntax=docker/dockerfile:1

WORKDIR $GOPATH/src/github.com/owenthereal/upterm
COPY . .
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go install ./cmd/uptermd/...
FROM golang:latest as builder

# Prepare for image
FROM alpine:latest
ARG TARGETOS TARGETARCH

MAINTAINER Owen Ou
LABEL org.opencontainers.image.source https://github.com/owenthereal/upterm
WORKDIR /src
ENV CGO_ENABLED=0
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg \
GOOS=$TARGETOS GOARCH=$TARGETARCH go install \
./cmd/...

RUN adduser -D uptermd
USER uptermd
FROM gcr.io/distroless/static

USER nonroot:nonroot

WORKDIR /app
ENV PATH="/app:${PATH}"

COPY --from=builder /go/bin/* /app
COPY --from=builder /go/bin/uptermd /app/

# sshd
EXPOSE 2222
Expand All @@ -27,3 +29,14 @@ EXPOSE 8080
EXPOSE 9090

ENTRYPOINT ["uptermd"]

FROM gcr.io/distroless/static as uptermd-fly

USER nonroot:nonroot

WORKDIR /app
ENV PATH="/app:${PATH}"

COPY --from=builder /go/bin/uptermd /go/bin/uptermd-fly /app/

ENTRYPOINT ["uptermd-fly"]
8 changes: 3 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,11 @@ install:
go install ./cmd/...

TAG ?= latest
REPO ?= ghcr.io/owenthereal/upterm/uptermd
DOCKER_BUILD_FLAGS ?= --load
.PHONY: docker_build
docker_build:
docker build -t ghcr.io/owenthereal/upterm/uptermd:$(TAG) -f Dockerfile.uptermd .

.PHONY: docker_push
docker_push: docker_build
docker push ghcr.io/owenthereal/upterm/uptermd:$(TAG)
docker buildx build -t $(REPO):$(TAG) -f Dockerfile.uptermd $(DOCKER_BUILD_FLAGS) .

GO_TEST_FLAGS ?= ""
.PHONY: test
Expand Down
32 changes: 32 additions & 0 deletions cmd/uptermd-fly/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"fmt"
"os"

"github.com/owenthereal/upterm/cmd/uptermd/command"
log "github.com/sirupsen/logrus"
)

func main() {
logger := log.New()

flyAppName := os.Getenv("FLY_APP_NAME")
if flyAppName == "" {
logger.Fatal("FLY_APP_NAME is not set")
}

flyMachineID := os.Getenv("FLY_MACHINE_ID")
if flyMachineID == "" {
logger.Fatal("FLY_MACHINE_ID is not set")
}

os.Setenv("UPTERMD_NODE_ADDR", fmt.Sprintf("%s.vm.%s.internal:2222", flyMachineID, flyAppName))
os.Setenv("UPTERMD_SSH_ADDR", "0.0.0.0:2222")
os.Setenv("UPTERMD_WS_ADDR", "0.0.0.0:8080")
os.Setenv("UPTERMD_HOSTNAME", "uptermd.upterm.dev")

if err := command.Root(logger).Execute(); err != nil {
logger.Fatal(err)
}
}
85 changes: 85 additions & 0 deletions cmd/uptermd/command/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package command

import (
"fmt"
"os"
"strings"

"github.com/owenthereal/upterm/server"
"github.com/owenthereal/upterm/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)

func Root(logger log.FieldLogger) *cobra.Command {
rootCmd := &rootCmd{}
cmd := &cobra.Command{
Use: "uptermd",
Short: "Upterm Daemon",
RunE: rootCmd.Run,
}

cmd.PersistentFlags().String("config", "", "server config")

cmd.PersistentFlags().StringP("ssh-addr", "", utils.DefaultLocalhost("2222"), "ssh server address")
cmd.PersistentFlags().StringP("ws-addr", "", "", "websocket server address")
cmd.PersistentFlags().StringP("node-addr", "", "", "node address")
cmd.PersistentFlags().StringSliceP("private-key", "", nil, "server private key")
cmd.PersistentFlags().StringSliceP("hostname", "", nil, "server hostname for public-key authentication certificate principals. If empty, public-key authentication is used instead.")

cmd.PersistentFlags().StringP("network", "", "mem", "network provider")
cmd.PersistentFlags().StringSliceP("network-opt", "", nil, "network provider option")

cmd.PersistentFlags().StringP("metric-addr", "", "", "metric server address")
cmd.PersistentFlags().BoolP("debug", "", os.Getenv("DEBUG") != "", "debug")

return cmd
}

type rootCmd struct {
}

func (cmd *rootCmd) Run(c *cobra.Command, args []string) error {
var opt server.Opt
if err := unmarshalFlags(c, &opt); err != nil {
return err
}

return server.Start(opt)
}

func unmarshalFlags(cmd *cobra.Command, opts interface{}) error {
v := viper.New()

cmd.Flags().VisitAll(func(flag *pflag.Flag) {
flagName := flag.Name
if flagName != "config" && flagName != "help" {
if err := v.BindPFlag(flagName, flag); err != nil {
panic(fmt.Errorf("error binding flag '%s': %w", flagName, err).Error())
}
}
})

v.AutomaticEnv()
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
v.SetEnvPrefix("UPTERMD")

cfgFile, err := cmd.Flags().GetString("config")
if err != nil {
return err
}

if _, err := os.Stat(cfgFile); err == nil {
v.SetConfigFile(cfgFile)
}

if err := v.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return fmt.Errorf("error loading config file %s: %w", cfgFile, err)
}
}

return v.Unmarshal(opts)
}
64 changes: 0 additions & 64 deletions cmd/uptermd/internal/command/root.go

This file was deleted.

2 changes: 1 addition & 1 deletion cmd/uptermd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"os"

"github.com/heroku/rollrus"
"github.com/owenthereal/upterm/cmd/uptermd/internal/command"
"github.com/owenthereal/upterm/cmd/uptermd/command"
log "github.com/sirupsen/logrus"
)

Expand Down
8 changes: 1 addition & 7 deletions fly.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@ app = "upterm"
kill_signal = "SIGINT"
kill_timeout = "5s"

[experimental]
cmd = [
"uptermd --ssh-addr 0.0.0.0:2222 --ws-addr 0.0.0.0:8080 --node-addr $(echo ${FLY_ALLOC_ID} | cut -f1 -d '-').vm.${FLY_APP_NAME}.internal:2222 --hostname uptermd.upterm.dev",
]
entrypoint = ["/bin/sh", "-c"]
auto_rollback = true

[build]
dockerfile = "Dockerfile.uptermd"
build-target = "uptermd-fly"

[[services]]
protocol = "tcp"
Expand Down
Loading

0 comments on commit 1846c3a

Please sign in to comment.