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
|
- uname -r
|
||||||
- hadolint --version
|
- hadolint --version
|
||||||
|
|
||||||
|
- name: golang
|
||||||
|
pull: always
|
||||||
|
image: docker.io/library/golang:1.18.5-alpine3.16
|
||||||
|
commands:
|
||||||
|
- uname -r
|
||||||
|
- go version
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
@ -47,6 +54,9 @@ trigger:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- pull
|
- pull
|
||||||
|
|
||||||
|
environment:
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: hugo-extended
|
- name: hugo-extended
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
@ -57,6 +67,44 @@ steps:
|
|||||||
- hugo version
|
- hugo version
|
||||||
- hugo --gc=true --minify
|
- 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
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
@ -178,6 +226,9 @@ node:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
|
||||||
|
environment:
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: hugo-extended
|
- name: hugo-extended
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
@ -204,12 +255,47 @@ steps:
|
|||||||
- hadolint --version
|
- hadolint --version
|
||||||
- hadolint Dockerfile
|
- 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
|
- name: build
|
||||||
pull: always
|
pull: always
|
||||||
image: tmaier/docker-compose:latest
|
image: tmaier/docker-compose:latest
|
||||||
depends_on:
|
depends_on:
|
||||||
- rm-intermediate
|
- rm-intermediate
|
||||||
- hadolint
|
- hadolint
|
||||||
|
- go fmt
|
||||||
|
- go vet
|
||||||
|
- go build
|
||||||
volumes:
|
volumes:
|
||||||
- name: s
|
- name: s
|
||||||
path: /var/run/docker.sock
|
path: /var/run/docker.sock
|
||||||
@ -237,6 +323,8 @@ volumes:
|
|||||||
- name: s
|
- name: s
|
||||||
host:
|
host:
|
||||||
path: /var/run/docker.sock
|
path: /var/run/docker.sock
|
||||||
|
- name: gopath
|
||||||
|
temp: {}
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -19,4 +19,11 @@ repos:
|
|||||||
language: system
|
language: system
|
||||||
entry: yamllint .
|
entry: yamllint .
|
||||||
pass_filenames: false
|
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
|
||||||
...
|
...
|
||||||
|
39
Dockerfile
39
Dockerfile
@ -1,28 +1,25 @@
|
|||||||
FROM immawanderer/fedora-hugo:linux-amd64 AS hugobuild
|
FROM docker.io/immawanderer/fedora-hugo:linux-amd64 AS hugobuild
|
||||||
RUN mkdir -pv /homepage
|
|
||||||
COPY . /homepage
|
|
||||||
|
|
||||||
WORKDIR /homepage
|
WORKDIR /homepage
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
RUN git submodule init \
|
RUN git submodule init \
|
||||||
&& git submodule update --recursive \
|
&& git submodule update --recursive \
|
||||||
&& hugo version
|
&& hugo version \
|
||||||
# "DL3059 info: Multiple consecutive `RUN` instructions.
|
&& hugo --minify --gc=true --cleanDestinationDir
|
||||||
# Consider consolidation."
|
|
||||||
# hadolint ignore=DL3059
|
|
||||||
RUN hugo --minify --gc=true
|
|
||||||
|
|
||||||
WORKDIR /
|
FROM docker.io/library/golang:1.18.5-alpine3.16 AS gobuild
|
||||||
|
COPY --from=hugobuild /homepage/ /homepage/
|
||||||
|
|
||||||
FROM nginx:mainline-alpine
|
WORKDIR /homepage
|
||||||
COPY --from=hugobuild /homepage/public/ /usr/share/nginx/html
|
|
||||||
|
|
||||||
# tripple slash reference
|
ARG VCS_REF=development
|
||||||
# https://stackoverflow.com/questions/5190966/using-sed-to-insert-tabs/5191165#5191165
|
|
||||||
RUN sed -i -e 's/^worker_processes auto;/worker_processes auto;/'\
|
RUN CGO_ENABLED=0 GOFLAGS='-trimpath -mod=readonly -modcacherw' \
|
||||||
-e "/^events {$/ a \\\tmulti_accept on;\n\tuse epoll;"\
|
go build -o homepage-app -v -ldflags "-s -w -X main.version=$VCS_REF" .
|
||||||
-e "/^http {$/ a \\\tserver_tokens off;\n\tetag off;\n"\
|
|
||||||
-e 's/#tcp_nopush/tcp_nopush/'\
|
FROM scratch
|
||||||
-e "/tcp_nopush/ a \\\ttcp_nodelay on;\n\terror_page 404 /404.html;"\
|
COPY --from=gobuild /homepage/homepage-app /homepage
|
||||||
-e "s/^ */$(printf '\t')/"\
|
|
||||||
/etc/nginx/nginx.conf
|
ENTRYPOINT ["/homepage"]
|
||||||
|
@ -10,7 +10,7 @@ services:
|
|||||||
- internal-nw
|
- internal-nw
|
||||||
- default
|
- default
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:1314:80
|
- 127.0.0.1:1314:1314
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
# So that traefik can listen to the Docker events
|
# So that traefik can listen to the Docker events
|
||||||
@ -26,7 +26,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- 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`)
|
- 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://stackoverflow.com/a/61976953
|
||||||
# ref: https://github.com/traefik/traefik/issues/563
|
# 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