embed homepage in a Go app
All checks were successful
continuous-integration/drone/pr Build is passing
All checks were successful
continuous-integration/drone/pr Build is passing
the entire './public' folder that Hugo produces is embedded into a variable of 'embed.FS' type and served directly using the default http mux that Go std offers. ci, pre-commit, Dockerfile and compose file have all been updated accordingly. nginx is no longer needed to front the site files, which enabled switching to a SCRATCH image containing just a single statically linked "homepage" app that has all files (html, css, js) embedded. the containers are otherwise empty (as the name SCRATCH suggests), which further decreases potential attack surface area.
This commit is contained in:
parent
d0c61e4847
commit
573c9da829
88
.drone.yml
88
.drone.yml
@ -31,6 +31,13 @@ steps:
|
||||
- uname -r
|
||||
- hadolint --version
|
||||
|
||||
- name: golang
|
||||
pull: always
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
commands:
|
||||
- uname -r
|
||||
- go version
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@ -47,6 +54,9 @@ trigger:
|
||||
depends_on:
|
||||
- pull
|
||||
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
steps:
|
||||
- name: hugo-extended
|
||||
pull: if-not-exists
|
||||
@ -57,6 +67,44 @@ steps:
|
||||
- hugo version
|
||||
- hugo --gc=true --minify
|
||||
|
||||
- name: go fmt
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- clone
|
||||
commands:
|
||||
- go fmt
|
||||
|
||||
- name: go vet
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go fmt
|
||||
commands:
|
||||
- go vet
|
||||
|
||||
- name: go build
|
||||
pull: if-not-exists
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go vet
|
||||
# wait until the site is output into './public'.
|
||||
- hugo-extended
|
||||
commands:
|
||||
- go build -v -ldflags "-s -w -X main.Version=${DRONE_COMMIT}" .
|
||||
|
||||
volumes:
|
||||
- name: gopath
|
||||
temp: {}
|
||||
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@ -178,6 +226,9 @@ node:
|
||||
depends_on:
|
||||
- build
|
||||
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
steps:
|
||||
- name: hugo-extended
|
||||
pull: if-not-exists
|
||||
@ -204,12 +255,47 @@ steps:
|
||||
- hadolint --version
|
||||
- hadolint Dockerfile
|
||||
|
||||
- name: go fmt
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- clone
|
||||
commands:
|
||||
- go fmt
|
||||
|
||||
- name: go vet
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go fmt
|
||||
commands:
|
||||
- go vet
|
||||
|
||||
- name: go build
|
||||
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go vet
|
||||
# wait until the site is output into './public'.
|
||||
- hugo-extended
|
||||
commands:
|
||||
- go build -v -ldflags "-s -w -X main.Version=${DRONE_COMMIT}" .
|
||||
|
||||
- name: build
|
||||
pull: always
|
||||
image: tmaier/docker-compose:latest
|
||||
depends_on:
|
||||
- rm-intermediate
|
||||
- hadolint
|
||||
- go fmt
|
||||
- go vet
|
||||
- go build
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
@ -237,6 +323,8 @@ volumes:
|
||||
- name: s
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
- name: gopath
|
||||
temp: {}
|
||||
|
||||
|
||||
---
|
||||
|
@ -19,4 +19,11 @@ repos:
|
||||
language: system
|
||||
entry: yamllint .
|
||||
pass_filenames: false
|
||||
- repo: https://github.com/dnephin/pre-commit-golang
|
||||
rev: v0.5.0
|
||||
hooks:
|
||||
- id: go-mod-tidy
|
||||
- id: go-unit-tests
|
||||
- id: golangci-lint
|
||||
- id: go-build
|
||||
...
|
||||
|
37
Dockerfile
37
Dockerfile
@ -1,28 +1,25 @@
|
||||
FROM immawanderer/fedora-hugo:linux-amd64 AS hugobuild
|
||||
RUN mkdir -pv /homepage
|
||||
COPY . /homepage
|
||||
FROM docker.io/immawanderer/fedora-hugo:linux-amd64 AS hugobuild
|
||||
|
||||
WORKDIR /homepage
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN git submodule init \
|
||||
&& git submodule update --recursive \
|
||||
&& hugo version
|
||||
# "DL3059 info: Multiple consecutive `RUN` instructions.
|
||||
# Consider consolidation."
|
||||
# hadolint ignore=DL3059
|
||||
RUN hugo --minify --gc=true
|
||||
&& hugo version \
|
||||
&& hugo --minify --gc=true --cleanDestinationDir
|
||||
|
||||
WORKDIR /
|
||||
FROM docker.io/library/golang:1.18.5-alpine3.16 AS gobuild
|
||||
COPY --from=hugobuild /homepage/ /homepage/
|
||||
|
||||
FROM nginx:mainline-alpine
|
||||
COPY --from=hugobuild /homepage/public/ /usr/share/nginx/html
|
||||
WORKDIR /homepage
|
||||
|
||||
# tripple slash reference
|
||||
# https://stackoverflow.com/questions/5190966/using-sed-to-insert-tabs/5191165#5191165
|
||||
RUN sed -i -e 's/^worker_processes auto;/worker_processes auto;/'\
|
||||
-e "/^events {$/ a \\\tmulti_accept on;\n\tuse epoll;"\
|
||||
-e "/^http {$/ a \\\tserver_tokens off;\n\tetag off;\n"\
|
||||
-e 's/#tcp_nopush/tcp_nopush/'\
|
||||
-e "/tcp_nopush/ a \\\ttcp_nodelay on;\n\terror_page 404 /404.html;"\
|
||||
-e "s/^ */$(printf '\t')/"\
|
||||
/etc/nginx/nginx.conf
|
||||
ARG VCS_REF=development
|
||||
|
||||
RUN CGO_ENABLED=0 GOFLAGS='-trimpath -mod=readonly -modcacherw' \
|
||||
go build -o homepage-app -v -ldflags "-s -w -X main.version=$VCS_REF" .
|
||||
|
||||
FROM scratch
|
||||
COPY --from=gobuild /homepage/homepage-app /homepage
|
||||
|
||||
ENTRYPOINT ["/homepage"]
|
||||
|
@ -10,7 +10,7 @@ services:
|
||||
- internal-nw
|
||||
- default
|
||||
ports:
|
||||
- 127.0.0.1:1314:80
|
||||
- 127.0.0.1:1314:1314
|
||||
restart: always
|
||||
volumes:
|
||||
# So that traefik can listen to the Docker events
|
||||
@ -26,7 +26,7 @@ services:
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.homepage.loadbalancer.server.port=80
|
||||
- traefik.http.services.homepage.loadbalancer.server.port=1314
|
||||
- traefik.http.routers.homepage.rule=Host(`localhost`) || Host(`127.0.0.1`) || Host(`homepage`) || Host(`6426tqrh4y5uobmo5y2csaip3m3avmjegd2kpa24sadekpxglbm34aqd.onion`)
|
||||
# ref: https://stackoverflow.com/a/61976953
|
||||
# ref: https://github.com/traefik/traefik/issues/563
|
||||
|
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module git.dotya.ml/dotya.ml/homepage
|
||||
|
||||
go 1.18
|
32
main.go
Normal file
32
main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var version = "development"
|
||||
|
||||
//go:embed public/*
|
||||
var embeddedPublic embed.FS
|
||||
|
||||
func main() {
|
||||
root, err := fs.Sub(embeddedPublic, "public")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fs := http.FileServer(http.FS(root))
|
||||
|
||||
http.Handle("/", fs)
|
||||
|
||||
log.Printf("app built from revision '%s'\n", version)
|
||||
log.Print("Listening on :1314...")
|
||||
|
||||
err = http.ListenAndServe(":1314", nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user