From 9471fb5734ecf6db62fff1b375a7c750293509f7 Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Sat, 5 Aug 2023 21:58:04 +1000 Subject: [PATCH] feat: docker build for controller --- .dockerignore | 1 + .github/workflows/ci.yml | 12 +++++++++++ .github/workflows/release.yml | 25 +++++++++++++++++++--- Dockerfile.controller | 36 ++++++++++++++++++++++++++++++++ Makefile | 7 ++++++- backend/controller/controller.go | 14 ++++++++----- 6 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 Dockerfile.controller diff --git a/.dockerignore b/.dockerignore index aeea82bd0..f84f56313 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ .hermit **/node_modules +**/build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c91bec55..9881967c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,12 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + - name: Cache Gradle + id: cache-gradle + uses: actions/cache@v3 + with: + path: ~/.gradle/caches/modules-2 + key: ${{ runner.os }}-gradle - name: Init Hermit uses: cashapp/activate-hermit@v1 - name: Test @@ -22,6 +28,12 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + - name: Cache Gradle + id: cache-gradle + uses: actions/cache@v3 + with: + path: ~/.gradle/caches/modules-2 + key: ${{ runner.os }}-gradle - name: Init Hermit uses: cashapp/activate-hermit@v1 - name: Test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4f585b9a7..ad10a721e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,7 @@ on: pull_request: name: Build Docker Images jobs: - build: + build-runner: name: Build Runner Docker Image runs-on: ubuntu-latest steps: @@ -14,7 +14,7 @@ jobs: - name: Init Hermit uses: cashapp/activate-hermit@v1 - name: Build - run: docker build -t $(git rev-parse --short HEAD) -t ghcr.io/tbd54566975/ftl:latest -f Dockerfile.runner . + run: docker build -t $(git rev-parse --short HEAD) -t ghcr.io/tbd54566975/ftl-runner:latest -f Dockerfile.runner . - name: Log in to the Container registry uses: docker/login-action@v1 with: @@ -23,4 +23,23 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Push if: github.ref == 'refs/heads/main' - run: docker push ghcr.io/tbd54566975/ftl:latest \ No newline at end of file + run: docker push ghcr.io/tbd54566975/ftl-runner:latest + build-controller: + name: Build Controller Docker Image + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Init Hermit + uses: cashapp/activate-hermit@v1 + - name: Build + run: docker build -t $(git rev-parse --short HEAD) -t ghcr.io/tbd54566975/ftl-controller:latest -f Dockerfile.controller . + - name: Log in to the Container registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Push + if: github.ref == 'refs/heads/main' + run: docker push ghcr.io/tbd54566975/ftl-controller:latest diff --git a/Dockerfile.controller b/Dockerfile.controller new file mode 100644 index 000000000..62b9b9aee --- /dev/null +++ b/Dockerfile.controller @@ -0,0 +1,36 @@ +FROM ubuntu:22.04 AS builder +RUN apt update +RUN apt install -y curl git + +# Copy Hermit bin stubs and install all packages. This is done +# separately so that Docker will cache the tools correctly. +COPY ./bin /src/bin +ENV PATH="/src/bin:$PATH" +WORKDIR /src + +# Install Hermit tools so Docker will cache them +RUN hermit install + +# Download Go dependencies separately so Docker will cache them +COPY go.mod go.sum ./ +RUN go mod download -x + +# Build +COPY . /src/ +RUN make build/release/ftl-controller + +# Finally create the runtime image. +FROM ubuntu:22.04 + +WORKDIR /root/ + +COPY --from=builder /src/build/release/ftl-controller . +RUN mkdir deployments + +EXPOSE 8892 + +ENV FTL_CONTROLLER_BIND="http://0.0.0.0:8899" +ENV FTL_CONTROLLER_ADVERTISE="http://127.0.0.1:8899" +ENV FTL_CONTROLLER_DSN="postgres://host.docker.internal/ftl?sslmode=disable&user=postgres&password=secret" + +CMD ["/root/ftl-controller"] \ No newline at end of file diff --git a/Makefile b/Makefile index ea7b3dd2e..4f2bf9c2c 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ help: ## This help. @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' .PHONY: release -release: build/release/ftl-controller build/release/ftl-runner build/release/ftl +release: build/release/ftl-controller build/release/ftl-runner build/release/ftl ## Build release binaries. build/release/ftl-controller: console/client/dist/index.html go build -o $@ -tags release -ldflags "-X main.version=$(VERSION)" ./cmd/$(shell basename $@) @@ -62,6 +62,11 @@ docker-runner: ## Build ftl-runner docker images. docker build --tag ftl-runner --platform=linux/amd64 \ -f Dockerfile.runner . +.PHONY: +docker-controller: ## Build ftl-controller docker images. + docker build --tag ftl-controller --platform=linux/amd64 \ + -f Dockerfile.controller . + .PHONY: protosync protosync: ## Synchronise external protos into FTL repo. protosync diff --git a/backend/controller/controller.go b/backend/controller/controller.go index 6413c5512..53940beda 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -36,9 +36,10 @@ import ( ) type Config struct { - Bind *url.URL `help:"Socket to bind to." default:"http://localhost:8892"` + Bind *url.URL `help:"Socket to bind to." default:"http://localhost:8892" env:"FTL_CONTROLLER_BIND"` + Advertise *url.URL `help:"Endpoint the Controller should advertise (use --bind if omitted)." default:"" env:"FTL_RUNNER_ADVERTISE"` Key model2.ControllerKey `help:"Controller key (auto)." placeholder:"C" default:"C00000000000000000000000000"` - DSN string `help:"DAL DSN." default:"postgres://localhost/ftl?sslmode=disable&user=postgres&password=secret"` + DSN string `help:"DAL DSN." default:"postgres://localhost/ftl?sslmode=disable&user=postgres&password=secret" env:"FTL_CONTROLLER_DSN"` RunnerTimeout time.Duration `help:"Runner heartbeat timeout." default:"10s"` DeploymentReservationTimeout time.Duration `help:"Deployment reservation timeout." default:"120s"` ArtefactChunkSize int `help:"Size of each chunk streamed to the client." default:"1048576"` @@ -114,7 +115,10 @@ func New(ctx context.Context, dal *dal2.DAL, config Config) (*Service, error) { clients: map[string]clients{}, key: key, } - go svc.heartbeatController(ctx, config.Bind) + if config.Advertise.String() == "" { + config.Advertise = config.Bind + } + go svc.heartbeatController(ctx, config.Advertise) go svc.reapStaleControllers(ctx) go svc.reapStaleRunners(ctx) go svc.releaseExpiredReservations(ctx) @@ -703,10 +707,10 @@ func (s *Service) reapStaleControllers(ctx context.Context) { } // Periodically update the DB with the current state of the controller. -func (s *Service) heartbeatController(ctx context.Context, addr *url.URL) { +func (s *Service) heartbeatController(ctx context.Context, advertiseAddr *url.URL) { logger := log.FromContext(ctx) for { - _, err := s.dal.UpsertController(ctx, s.key, addr.String()) + _, err := s.dal.UpsertController(ctx, s.key, advertiseAddr.String()) if err != nil { logger.Errorf(err, "Failed to heartbeat controller") }