This commit is contained in:
Andre Heber
2024-08-20 23:51:59 +02:00
commit ea3b86e8cd
20 changed files with 120 additions and 0 deletions

44
Dockerfile Normal file
View File

@ -0,0 +1,44 @@
# Use Alpine as the base image
FROM alpine:3.20.2
# Install necessary packages & Go
RUN apk add --no-cache \
alpine-base \
logrotate \
dcron \
go \
s6-overlay
# Set up the s6-overlay configuration
COPY etc /etc
# Set up Go environment
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
# Copy the Go application
COPY main.go /app/main.go
# Build the Go application
RUN go build -o /usr/local/bin/myapp /app/main.go
# Set up syslog
#COPY syslog.conf /etc/syslog.conf
#RUN mkdir -p /var/log/syslog
# Set up logrotate
#COPY logrotate.conf /etc/logrotate.conf
# Set up watchdog
#COPY watchdog.conf /etc/watchdog.conf
# Copy your application
# COPY myapp /usr/local/bin/myapp
# Set up s6 service for your app
#COPY run /etc/services.d/myapp/run
ENV LOG_LEVEL=WARNING
# Use s6-overlay as the entrypoint
ENTRYPOINT ["/init"]

17
README.md Normal file
View File

@ -0,0 +1,17 @@
# Alpine with S6-Overlay
I want a docker image that behaves more like a VM:
1. I can start / stop many processes, also the main process (usually PID 1)
Why? To test things out. Changing environment variables, debugging with the coredump file or recompiling the app without crashing the container follows much more my development process
2. Logging to a seperate file with logrotation
Why? Docker logs (and Kibana) are a pain in the ass!
3. Watchdog: k8s restarts containers when they are crashing. That should be done by the s6-overlay.
## Tested
- [x] Starting & Stopping services with `s6-rc start myapp` and `s6-rc stop myapp`
- [x] `docker exec` into the container and run myapp manually, it uses the env vars of the shell
- [x] Logging: `/var/log/myapp/current` is filled
- [ ] Logrotation
- [ ] Cron

View File

@ -0,0 +1 @@
oneshot

View File

@ -0,0 +1,3 @@
if { mkdir -p /var/log/myapp }
if { chown nobody:nogroup /var/log/myapp }
chmod 02755 /var/log/myapp

View File

@ -0,0 +1 @@
myapp

View File

@ -0,0 +1 @@
myapp-pipeline

View File

@ -0,0 +1,2 @@
#!/bin/sh
exec logutil-service /var/log/myapp

View File

@ -0,0 +1 @@
longrun

View File

@ -0,0 +1,9 @@
#!/bin/sh
if test "$1" -eq 256 ; then
e=$((128 + $2))
else
e="$1"
fi
echo "$e" > /run/s6-linux-init-container-results/exitcode

View File

@ -0,0 +1 @@
myapp-log

View File

@ -0,0 +1,3 @@
#!/command/with-contenv sh
exec 2>&1
exec s6-setuidgid daemon /usr/local/bin/myapp

View File

@ -0,0 +1 @@
longrun

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module example.com/loglevel
go 1.22.3

26
main.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"log"
"os"
"time"
)
func main() {
// Configure logging to include timestamp
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
// Read LOG_LEVEL from environment variable
logLevel := os.Getenv("LOG_LEVEL")
if logLevel == "" {
logLevel = "INFO" // Default log level
}
log.Printf("Starting application with LOG_LEVEL: %s", logLevel)
// Infinite loop to log every 2 seconds
for {
log.Printf("Current LOG_LEVEL: %s", logLevel)
time.Sleep(2 * time.Second)
}
}

7
run Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/with-contenv sh
# Start your application
exec /usr/local/bin/myapp
# Touch the watchdog file
touch /var/run/myapp.touch