From 57e9e7146c2ce1aa8a271c51fdd64e347983b5da Mon Sep 17 00:00:00 2001 From: Ben Pate Date: Sat, 27 Apr 2024 16:06:28 -0600 Subject: [PATCH] Refactoring Docker configuration - upgrade to Go 1.22.2 - adding ffmpeg dependency (gulp) - splitting demo and production configurations (production still needs testing) - renaming config files (since the "development" container didn't work out so great) - adding "createOwner" switch for localhost servers - single thread all initialization (including createOwner step) - removing entrypoint.sh because we're now populating starter configs, so the server doesn't have to wait for config.json anymore --- config/domain.go | 1 + docker-compose-demo.yml | 58 -------------------------- docker-compose-production.yml | 19 +++++++++ docker-compose.yml | 47 ++++++++++++++------- docker/demo-dockerfile | 2 +- docker/{demo-config.json => demo.json} | 3 +- docker/entrypoint.sh | 21 ---------- docker/{Dockerfile => prod-dockerfile} | 10 +++-- service/domain.go | 37 ++++++++-------- 9 files changed, 78 insertions(+), 120 deletions(-) delete mode 100644 docker-compose-demo.yml create mode 100644 docker-compose-production.yml rename docker/{demo-config.json => demo.json} (96%) delete mode 100755 docker/entrypoint.sh rename docker/{Dockerfile => prod-dockerfile} (75%) diff --git a/config/domain.go b/config/domain.go index 20b1b2d5..243352f2 100644 --- a/config/domain.go +++ b/config/domain.go @@ -16,6 +16,7 @@ type Domain struct { SMTPConnection SMTPConnection `json:"smtp" bson:"smtp"` // Information for connecting to an SMTP server to send email on behalf of the domain. Owner Owner `json:"owner" bson:"owner"` // Information about the owner of this domain KeyEncryptingKey string `json:"keyEncryptingKey" bson:"keyEncryptingKey"` // Key used to encrypt/decrypt JWT keys stored in the database + CreateOwner bool `json:"createOwner" bson:"createOwner"` // TRUE if the owner should be created when the domain is created } // NewDomain returns a fully initialized Domain object. diff --git a/docker-compose-demo.yml b/docker-compose-demo.yml deleted file mode 100644 index 856256f5..00000000 --- a/docker-compose-demo.yml +++ /dev/null @@ -1,58 +0,0 @@ -# This docker-compose file starts up a Emissary server where you -# can "kick the tires" and see how it works. You should probably -# not use this in production. -# -# It defaults to serving one domain "localhost" on port 8080. -name: emissary_demo - -services: - - # This is the Emissary server that runs a single "localhost" domain on port 8080. - # It runs on http://localhost:8080 - server: - container_name: emissary_demo_server - build: - context: . - dockerfile: ./docker/demo-dockerfile - ports: - - "8080:8080" - environment: - - EMISSARY_CONFIG=file:///data/config/config.json - depends_on: - - mongodb - volumes: - - config:/data/config - - uploads:/data/uploads - - # The setup tool creates/modifies the server configuration, - # although you probably won't have to use it much for this demo. - # It runs on http://localhost:8888 - setup: - container_name: emissary_demo_setup - build: - context: . - dockerfile: ./docker/demo-dockerfile - ports: - - "8888:8888" - environment: - - EMISSARY_CONFIG=file:///data/config/demo.json - command: ["--setup", "--port", "8888"] - depends_on: - - mongodb - volumes: - - config:/data/config - - # This mongo database stores data for the Emissary site. - # You can connect to it using any MongoDB client. - mongodb: - container_name: emissary_demo_database - image: "mongo:latest" - ports: - - "27017:27017" - volumes: - - mongo:/data/db - -volumes: - config: - mongo: - uploads: diff --git a/docker-compose-production.yml b/docker-compose-production.yml new file mode 100644 index 00000000..bfa5aa14 --- /dev/null +++ b/docker-compose-production.yml @@ -0,0 +1,19 @@ +# This docker-compose file starts up a Emissary server for +# production use. This file assumes: +# 1) you will configure Emissary using a mongodb database. +# 2) the mongo database exists outside of this Docker config. +# 3) you have configured ENVIRONMENT VARIABLES to point to it. +# +# After installing this server, you will need to run the +# setup tool from another location to configure the server's +# settings and domains + +name: emissary_prod +services: + emissary: + build: + context: . + dockerfile: ./docker/prod-dockerfile + ports: + - "80:80" + - "443:443" diff --git a/docker-compose.yml b/docker-compose.yml index 2c04e93f..91711474 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,23 +1,37 @@ -version: '3.8' +# This docker-compose file starts up a Emissary server where you +# can "kick the tires" and see how it works. You should probably +# not use this in production. +# +# It defaults to serving one domain "localhost" on port 8080. +name: emissary_demo + services: - emissary: + + # This is the Emissary server that runs a single "localhost" domain on port 8080. + # It runs on http://localhost:8080 + server: + container_name: emissary_demo_server build: context: . - dockerfile: ./docker/Dockerfile + dockerfile: ./docker/demo-dockerfile ports: - "8080:8080" environment: - EMISSARY_CONFIG=file:///data/config/config.json - - WAIT_FOR_CONFIG=1 depends_on: - mongodb - - smtp volumes: - - configdata:/data/config + - config:/data/config + - uploads:/data/uploads + + # The setup tool creates/modifies the server configuration, + # although you probably won't have to use it much for this demo. + # It runs on http://localhost:8888 setup: + container_name: emissary_demo_setup build: context: . - dockerfile: ./docker/Dockerfile + dockerfile: ./docker/demo-dockerfile ports: - "8888:8888" environment: @@ -25,19 +39,20 @@ services: command: ["--setup", "--port", "8888"] depends_on: - mongodb - - smtp volumes: - - configdata:/data/config + - config:/data/config + + # This mongo database stores data for the Emissary site. + # You can connect to it using any MongoDB client. mongodb: + container_name: emissary_demo_database image: "mongo:latest" ports: - "27017:27017" volumes: - - mongodata:/data/db - smtp: - image: ghcr.io/literalgarage/smtp-logger:latest - ports: - - "8025:8025" + - mongo:/data/db + volumes: - mongodata: - configdata: + config: + mongo: + uploads: diff --git a/docker/demo-dockerfile b/docker/demo-dockerfile index 0f57568c..856f608a 100644 --- a/docker/demo-dockerfile +++ b/docker/demo-dockerfile @@ -27,7 +27,7 @@ WORKDIR /app # Copy the Pre-built binary file from the previous stage COPY --from=builder /app/emissary . -COPY --from=builder /app/docker/demo-config.json /data/config/config.json +COPY --from=builder /app/docker/demo.json /data/config/config.json # Entrypoint script ENTRYPOINT [ "/app/emissary" ] diff --git a/docker/demo-config.json b/docker/demo.json similarity index 96% rename from docker/demo-config.json rename to docker/demo.json index d67fafc2..4925eb7b 100755 --- a/docker/demo-config.json +++ b/docker/demo.json @@ -55,5 +55,6 @@ "adminEmail": "", "httpPort": 8080, "httpsPort": 0, - "debugLevel": "Trace" + "debugLevel": "Debug", + "createOwner": true } \ No newline at end of file diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh deleted file mode 100755 index 3bc973c9..00000000 --- a/docker/entrypoint.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Blow up if EMISSARY_CONFIG is not set -if [ -z "$EMISSARY_CONFIG" ]; then - echo "EMISSARY_CONFIG must be set. Exiting." - exit 1 -fi - -# If WAIT_FOR_CONFIG is set, wait for the config file to exist -# before starting emissary. -if [ -n "$WAIT_FOR_CONFIG" ]; then - CONFIG_PATH="${EMISSARY_CONFIG#file://}" - echo "Waiting for config file to exist at ${CONFIG_PATH}..." - while [ ! -f ${CONFIG_PATH} ]; do - sleep 0.25 - done -fi - -# Start emissary with the provided arguments -exec /app/emissary "$@" - diff --git a/docker/Dockerfile b/docker/prod-dockerfile similarity index 75% rename from docker/Dockerfile rename to docker/prod-dockerfile index 11665046..f27e8ed8 100644 --- a/docker/Dockerfile +++ b/docker/prod-dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21-bookworm as builder +FROM golang:1.22.2-bookworm as builder # Set the Current Working Directory inside the container WORKDIR /app @@ -18,11 +18,15 @@ RUN go build -o emissary server.go # Start a new stage from scratch FROM debian:bookworm-slim +# Install ffmpeg +# This is required for audio/video transcoding +RUN apt-get update -y +RUN apt-get install -y ffmpeg + WORKDIR /app # Copy the Pre-built binary file from the previous stage COPY --from=builder /app/emissary . -COPY --from=builder /app/docker/entrypoint.sh . # Entrypoint script -ENTRYPOINT [ "/app/entrypoint.sh" ] +ENTRYPOINT [ "/app/emissary" ] diff --git a/service/domain.go b/service/domain.go index 1d571ea9..2adc111c 100644 --- a/service/domain.go +++ b/service/domain.go @@ -155,26 +155,23 @@ func (service *Domain) Save(domain model.Domain, note string) error { service.domain = domain // If this is the first time saving a local domain, create an initial admin user. - if firstSave && service.IsLocalhost() { - - go func() { - log.Trace().Msg("Creating admin user for local host") - - admin := model.NewUser() - admin.DisplayName = "Admin" - admin.Username = "admin" - admin.EmailAddress = "admin@localhost" - admin.SetPassword("admin") - admin.IsOwner = true - admin.IsPublic = true - - if err := service.userService.Save(&admin, "Create admin user for local host"); err != nil { - derp.Report(derp.Wrap(err, "service.Domain.Save", "Error creating admin user for local host")) - return - } - - log.Trace().Msg("Added admin user for local host") - }() + if firstSave && service.configuration.CreateOwner && service.IsLocalhost() { + + log.Trace().Msg("Creating admin user for local host") + + admin := model.NewUser() + admin.DisplayName = "Admin" + admin.Username = "admin" + admin.EmailAddress = "admin@localhost" + admin.SetPassword("admin") + admin.IsOwner = true + admin.IsPublic = true + + if err := service.userService.Save(&admin, "Create admin user for local host"); err != nil { + return derp.Wrap(err, "service.Domain.Save", "Error creating admin user for local host") + } + + log.Trace().Msg("Added admin user for local host") } return nil