Skip to content

Commit

Permalink
fix: switch to smaller faster ko builds without qemu (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgabeler-lee-6rs committed Feb 15, 2025
2 parents 20a7b3f + 183a0d5 commit 53fa8ff
Show file tree
Hide file tree
Showing 11 changed files with 386 additions and 441 deletions.
90 changes: 32 additions & 58 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,9 @@ jobs:
name: Restore module cache
keys:
- go-mod-v1-{{ checksum "go.sum" }}
# - restore_cache:
# name: Restore similar AIO build cache
# keys:
# - go-build-aio-v1-cgo<< parameters.cgo >>-{{ checksum "/tmp/cache-time-limit" }}-{{ .Revision }}
# - go-build-aio-v1-cgo<< parameters.cgo >>-{{ checksum "/tmp/cache-time-limit" }}-

- run: go tool mage -v get
# gotestsum is included in the cimg/go image
# - run: go tool mage -v installCITools
# however protobuf is not
- run: go mod download
- run: go mod verify
- run: go tool mage -v installProtobufTools
- run: go tool mage -v generate:force
# make sure committed generated code was up to date
Expand All @@ -63,7 +56,7 @@ jobs:
- run:
name: Ensure golangci-lint is up to date
command: |
if ! golangci-lint version | fgrep -q 'built with go1.24.0' ; then
if golangci-lint version | fgrep -q 'built with go1.23' ; then
cd $(mktemp -d)
wget https://github.com/golangci/golangci-lint/releases/download/v1.64.5/golangci-lint-1.64.5-linux-amd64.tar.gz
tar -axf golangci-lint-1.64.5-linux-amd64.tar.gz
Expand Down Expand Up @@ -106,7 +99,7 @@ jobs:

- run:
name: Validate service is working (mmmbbb)
command: go tool mage -v testSmoke mmmbbb localhost:3001
command: go tool mage -v testSmoke mmmbbb localhost:8084

- run:
name: Coverage HTML report
Expand All @@ -127,11 +120,6 @@ jobs:
key: go-mod-v1-{{ checksum "go.sum" }}
paths:
- "/home/circleci/go/pkg"
# - save_cache:
# name: Save AIO build cache
# key: go-build-aio-v1-cgo<< parameters.cgo >>-{{ checksum "/tmp/cache-time-limit" }}-{{ .Revision }}
# paths:
# - ~/.cache/go-build

# post to slack if `main` fails to build
- when:
Expand All @@ -144,10 +132,11 @@ jobs:

publish-docker-multiarch:
docker:
- image: cimg/go:1.23
- image: cimg/go:1.24
resource_class: large
environment:
GOPRIVATE: "go.6river.tech/*,github.com/6RiverSystems/*"
GOMAXPROCS: "4"
steps:
- checkout
- run:
Expand All @@ -157,11 +146,6 @@ jobs:
name: Restore module cache
keys:
- go-mod-v1-{{ checksum "go.sum" }}
- restore_cache:
name: Restore similar multiarch build cache
keys:
- go-build-multiarch-v1-{{ checksum "/tmp/cache-time-limit" }}-{{ .Revision }}
- go-build-multiarch-v1-{{ checksum "/tmp/cache-time-limit" }}-
# for Go modules, we only need version numbers on `main`, as Go can
# pull any other git commit by hash. We do need a version tag for
# docker for this package however, just don't need it to be a git
Expand All @@ -181,52 +165,42 @@ jobs:
- store_artifacts:
name: Capture chosen version
path: .version
- run: go tool mage -v get
# gotestsum is included in the cimg/go image
# - run: go tool mage -v installCITools
# however protobuf is not
- run: go mod download
- run: go mod verify
- run: go tool mage -v installProtobufTools
- run: go tool mage -v generate:force
- setup_remote_docker
- sixrs-gke/docker-login
- run:
name: Initialize docker buildx
name: Build docker test image
command: |
docker run --privileged --rm tonistiigi/binfmt --install all
docker context create multiarch-context
docker buildx create --name mmmbbb-multiarch --driver docker-container --bootstrap --use multiarch-context
- run:
name: Build multiarch binaries
command: go tool mage -v releaseBinaries
- run:
name: Build multiarch docker images
command: go tool mage -v docker:multiarchBuildAll
go tool ko resolve --local --platform linux/amd64 -f <( echo ko://./cmd/mmmbbb ) | head -n1 | tee /tmp/testimage.txt
- run:
name: Verify docker images
command: |
set -xeuo pipefail
for plat in amd64 arm64 ; do
go tool mage -v docker:multiarchLoadArch mmmbbb $plat
docker run --rm --platform linux/$plat --entrypoint /app/mmmbbb mmmbbb:$(<.version) --version
# fire this one into the background for the smoke test run
docker run --name mmmbbb-smoke-$plat --rm --platform linux/$plat mmmbbb:$(<.version) &
pid=$!
# can't contact the remote docker directly, so we have to build
# the mage binary, copy it over, and exec it
CGO_ENABLED=0 go tool mage -v -compile magebinary-$plat -goarch $plat
docker cp magebinary-$plat mmmbbb-smoke-$plat:/
# this should ask the app to shut down at the end
docker exec mmmbbb-smoke-$plat /magebinary-$plat -v testSmokeCore mmmbbb localhost:8084
wait $pid
done
docker run --rm $(</tmp/testimage.txt) --version
# fire this one into the background for the smoke test run
docker run --name mmmbbb-smoke --rm $(</tmp/testimage.txt) &
pid=$!
# can't contact the remote docker directly, so we have to build
# the mage binary, copy it over, and exec it
CGO_ENABLED=0 go tool mage -v -compile magebinary
docker cp magebinary mmmbbb-smoke:/
rm -f magebinary
# this should ask the app to shut down at the end
docker exec mmmbbb-smoke /magebinary -v testSmokeCore mmmbbb localhost:8084
wait $pid
- run:
name: Push multiarch docker images
command: go tool mage -v docker:multiarchPushAll
- save_cache:
name: Save multiarch build cache
key: go-build-multiarch-v1-{{ checksum "/tmp/cache-time-limit" }}-{{ .Revision }}
paths:
- ~/.cache/go-build
name: Publish docker images
command: |
set -xeuo pipefail
version=$(<.version)
args=(--bare --tags "$version")
if [ "$CIRCLE_BRANCH" = "main" ]; then
args+=(--tags latest)
fi
KO_DOCKER_REPO=us-docker.pkg.dev/plasma-column-128721/gcr.io/mmmbbb go tool ko build "${args[@]}" ./cmd/mmmbbb
workflows:
build-workflow:
Expand All @@ -252,4 +226,4 @@ workflows:
branches:
only:
- main
- publish/*
- /^publish\/.*/
25 changes: 13 additions & 12 deletions .docker-deps/entrypoint.sh → .ko.yaml
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/sh
# Copyright (c) 2021 6 River Systems
# Copyright (c) 2025 6 River Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
Expand All @@ -18,13 +17,15 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


# TODO: this should be production-y with all the self-labelling shenaningans
# from node_base

# hack: see notes on CMD in Dockerfile for what is going on here
if [ "$*" = '/app/${BINARYNAME}' ]; then
exec "/app/${BINARYNAME}"
else
exec "$@"
fi
builds:
- id: mmmbbb
main: ./cmd/mmmbbb
env:
- "GOPRIVATE=go.6river.tech/*,github.com/6RiverSystems/*"
- CGO_ENABLED=0
ldflags:
- "-s -w"
- '-extldflags "-static"'
defaultPlatforms:
- linux/amd64
- linux/arm64
63 changes: 0 additions & 63 deletions Dockerfile

This file was deleted.

20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,21 @@ This will be run automatically by `6mon`.

### For others

You can build and run the `mmmbbb` app locally, or you can use our published
Docker image `6river/mmmbbb`. The latter is simpler.
You can build and run the `mmmbbb` app locally, or you can use the bundled
[ko](https://ko.build/) configuration to build a docker image.

The docker image defaults to using a SQLite back-end, which is stored in a
`/data` volume in the container. This is done to minimize the amount of setup
required, but it should be noted that the PostgreSQL backend has considerably
better performance.
The docker image defaults to using a SQLite back-end, which is stored
ephemerally in `/tmp` in the container. This is done to minimize the amount of
setup required, but it should be noted that the PostgreSQL backend has
considerably better performance in addition to allowing data to persist across
container instantiations.

In its simplest form, you can use:

```shell
docker run --rm --publish 8084-8085:8084-8085/tcp 6river/mmmbbb
```

If you want to keep the SQLite database across runs, add
`--volume /local/path:/data` to have the database kept in `/local/path/mmmbbb.sqlite`.

### Initializing a PostgreSQL Database

The application will create all the tables it needs automatically, as long as it
Expand Down Expand Up @@ -80,13 +78,13 @@ environment variables).
SQLite as a backend currently requires explicitly specifying several extra
parameters in the `DATABASE_URL`.

CGo enabled (`mattn` driver):
CGo enabled (`mattn` driver, only enabled if building from source):

```text
?_fk=true&_journal_mode=wal&cache=private&_busy_timeout=10000&_txlock=immediate
```

CGo disabled (`modernc` driver):
CGo disabled (`modernc` driver, this is what `ko`-built containers will use):

```text
?_pragma=foreign_keys(1)&_pragma=journal_mode(wal)&_pragma=busy_timeout(10000)&_txlock=immediate
Expand Down
19 changes: 19 additions & 0 deletions cmd/mmmbbb/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ func main() {
}
}

// if running in a ko-built container, set some env defaults that we would
// have otherwise embedded via the Dockerfile
if os.Getenv("KO_DATA_PATH") != "" {
if os.Getenv("NODE_ENV") == "" {
os.Setenv("NODE_ENV", "production")
}
if os.Getenv("DATABASE_URL") == "" {
// default to an in-container SQLite database to simplify usage as a drop-in
os.Setenv("DATABASE_URL",
"sqlite:///tmp/mmmbbb.sqlite?"+
"_pragma=foreign_keys(1)&"+
"_pragma=journal_mode(wal)&"+
"_pragma=busy_timeout(10000)&"+
"cache=private&"+
"_txlock=immediate",
)
}
}

if exitCode, err := NewApp().main(); err != nil {
panic(err)
} else if exitCode != 0 {
Expand Down
2 changes: 1 addition & 1 deletion defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
package defaults

const (
Port = 3001
Port = 8084
GRPCOffset = 1
)
Loading

0 comments on commit 53fa8ff

Please sign in to comment.