feat: initial docker support

This commit is contained in:
Paul Pan 2023-07-15 18:14:50 +08:00
parent a0c36c1606
commit 175d90b147
6 changed files with 238 additions and 131 deletions

98
.gitignore vendored
View File

@ -1,96 +1,2 @@
### Project
/tmp
/server
/runner
my.secrets
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
/woj
/config.yaml

31
Dockerfile Normal file
View File

@ -0,0 +1,31 @@
# builder
FROM golang:alpine AS builder
ENV GOPROXY=https://goproxy.cn
WORKDIR /builder
RUN apk add --no-cache git make
RUN go install github.com/swaggo/swag/cmd/swag@latest
COPY go.mod /builder/go.mod
COPY go.sum /builder/go.sum
RUN go mod download
COPY . /builder
RUN make build
# main image
FROM alpine:latest
WORKDIR /app
RUN apk --no-cache add tzdata ca-certificates libc6-compat
COPY --from=builder /builder/config.docker.yaml /app
COPY --from=builder /builder/docker-entrypoint.sh /app
COPY --from=builder /builder/resource/frontend /app/resource/frontend
COPY --from=builder /builder/resource/runner /app/resource/runner
COPY --from=builder /builder/woj /app
ENTRYPOINT ["/app/docker-entrypoint.sh"]

35
config.docker.yaml Normal file
View File

@ -0,0 +1,35 @@
WebServer:
Address: ${WEB_SERVER_ADDRESS}
Port: ${WEB_SERVER_PORT}
JwtSigningKey: ${WEB_SERVER_JWT_SIGNING_KEY}
JwtExpireHour: ${WEB_SERVER_JWT_EXPIRE_HOUR}
Redis:
Db: ${REDIS_DB}
QueueDb: ${REDIS_QUEUE_DB}
Address: ${REDIS_ADDRESS_PORT}
Password: ${REDIS_PASSWORD}
Database:
Host: ${DATABASE_HOST}
Port: ${DATABASE_PORT}
User: ${DATABASE_USER}
Password: ${DATABASE_PASSWORD}
Database: ${DATABASE_NAME}
Prefix: ${DATABASE_PREFIX}
MaxOpenConns: ${DATABASE_MAX_OPEN_CONNS}
MaxIdleConns: ${DATABASE_MAX_IDLE_CONNS}
ConnMaxLifetime: ${DATABASE_CONN_MAX_LIFETIME}
Storage:
Endpoint: ${STORAGE_ENDPOINT}
UseSSL: ${STORAGE_USE_SSL}
AccessKey: ${STORAGE_ACCESS_KEY}
SecretKey: ${STORAGE_SECRET_KEY}
Bucket: ${STORAGE_BUCKET}
Metrics:
Namespace: ${METRICS_NAMESPACE}
Subsystem: ${METRICS_SUBSYSTEM}
Development: ${DEVELOPMENT}

View File

@ -1,35 +0,0 @@
WebServer:
Address: 0.0.0.0
Port: 8000
JwtSigningKey: 'rq67SdQIRABhHq40'
JwtExpireHour: 12
Redis:
Db: 0
QueueDb: 1
Address: '127.0.0.1:6379'
Password: ''
Database:
Host: '127.0.0.1'
Port: 5432
User: 'dev'
Password: 'password'
Database: 'dev'
Prefix: 'oj_'
MaxOpenConns: 100
MaxIdleConns: 60
ConnMaxLifetime: 60
Storage:
Endpoint: '127.0.0.1:9000'
UseSSL: false
AccessKey: 'EHd5Zj56QrTivhFI'
SecretKey: 'FUHy4RW1mn0Kbr5pibDZ6R2F9116FZKY'
Bucket: 'woj'
Metrics:
Namespace: 'OJ'
Subsystem: 'server'
Development: true

86
docker-compose.yml Normal file
View File

@ -0,0 +1,86 @@
version: "3"
services:
server:
build: .
restart: unless-stopped
command: web
environment:
- REDIS_ADDRESS_PORT=cache:6379
- DATABASE_HOST=db
- DATABASE_USER=dev
- DATABASE_PASSWORD=password
- DATABASE_NAME=dev
- STORAGE_ENDPOINT=minio:9000
- STORAGE_ACCESS_KEY=access_key
- STORAGE_SECRET_KEY=secret_key
- STORAGE_BUCKET=woj
- DEVELOPMENT=true
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
storage:
condition: service_healthy
cache:
condition: service_healthy
db:
condition: service_healthy
ports:
- "8000:8000"
#runner:
# build: .
# restart: unless-stopped
# command: runner
# environment:
# - REDIS_ADDRESS_PORT=cache:6379
# - DEVELOPMENT=true
# volumes:
# - runner:/app/resource/runner/user
# - /etc/timezone:/etc/timezone:ro
# - /etc/localtime:/etc/localtime:ro
# depends_on:
# - cache
storage:
image: minio/minio:latest
restart: unless-stopped
healthcheck:
test: [ "CMD", "echo", "ok" ]
interval: 5s
entrypoint: sh
command: -c 'mkdir -p /data/woj && minio server /data'
environment:
MINIO_ACCESS_KEY: "access_key"
MINIO_SECRET_KEY: "secret_key"
volumes:
- storage:/data
cache:
image: redis:alpine
restart: unless-stopped
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 5s
volumes:
- cache:/data
db:
image: postgres:alpine
restart: unless-stopped
healthcheck:
test: [ "CMD", "pg_isready", "-U", "dev" ]
interval: 5s
environment:
- POSTGRES_USER=dev
- POSTGRES_PASSWORD=password
- POSTGRES_DB=dev
volumes:
- db:/var/lib/postgresql/data
volumes:
runner:
storage:
cache:
db:

84
docker-entrypoint.sh Executable file
View File

@ -0,0 +1,84 @@
#!/bin/ash
set -eo pipefail
COLOR_RED="\e[0;31m"
COLOR_GREEN="\e[0;32m"
COLOR_YELLOW="\e[0;33m"
COLOR_NONE="\e[0m"
function log_info() { echo -e "${COLOR_GREEN}$*${COLOR_NONE}" 1>&2; }
function log_warn() { echo -e "${COLOR_YELLOW}$*${COLOR_NONE}" 1>&2; }
function log_error() { echo -e "${COLOR_RED}$*${COLOR_NONE}" 1>&2; }
log_info "extracting env vars"
function check_env() {
# $1 -> var name
# $2 -> default value
# $3 -> quota or not
val=$(eval "echo -n \${$1}")
if test -z "$val"; then
log_warn "Environment variable $1 is not set, using default value \"$2\""
export "$1"="$2"
else
log_info "Using $1=$val"
fi
if "$3"; then
val=$(eval "echo -n \${$1}")
# shellcheck disable=SC2140
export "$1"="'$val'"
fi
# echo -n ">>>>> "
# eval "echo -n \${$1}"
# echo " <<<<<"
}
check_env "WEB_SERVER_ADDRESS" "0.0.0.0" true
check_env "WEB_SERVER_PORT" 8000 false
check_env "WEB_SERVER_JWT_SIGNING_KEY" "$(head -n 10 /dev/urandom | md5sum | cut -c 1-32)" true
check_env "WEB_SERVER_JWT_EXPIRE_HOUR" 12 false
check_env "REDIS_DB" 0 false
check_env "REDIS_QUEUE_DB" 1 false
check_env "REDIS_ADDRESS_PORT" "redis:6379" true
check_env "REDIS_PASSWORD" "" true
check_env "DATABASE_HOST" "postgres" true
check_env "DATABASE_PORT" 5432 false
check_env "DATABASE_USER" "dev" true
check_env "DATABASE_PASSWORD" "password" true
check_env "DATABASE_NAME" "dev" true
check_env "DATABASE_PREFIX" "oj_" true
check_env "DATABASE_MAX_OPEN_CONNS" 100 false
check_env "DATABASE_MAX_IDLE_CONNS" 60 false
check_env "DATABASE_CONN_MAX_LIFETIME" 60 false
check_env "STORAGE_ENDPOINT" "minio:9000" true
check_env "STORAGE_USE_SSL" "false" false
check_env "STORAGE_ACCESS_KEY" "access_key" true
check_env "STORAGE_SECRET_KEY" "secret_key" true
check_env "STORAGE_BUCKET" "woj" true
check_env "METRICS_NAMESPACE" "woj" true
check_env "METRICS_SUBSYSTEM" "server" true
check_env "DEVELOPMENT" false false
rm -f /tmp/tmp.yaml
(
echo "cat <<EOF >/app/config.yaml"
cat /app/config.docker.yaml
echo "EOF"
) >/tmp/tmp.yaml
if [ -f '/app/config.yaml' ]; then
log_info "config.yaml already exists, skip"
else
log_info "creating config.yaml"
. /tmp/tmp.yaml || (log_error "failed to create config.yaml" && exit 1)
fi
log_info "starting woj"
#cat /app/config.yaml
exec /app/woj "$@"