init
This commit is contained in:
44
Dockerfile
Normal file
44
Dockerfile
Normal 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
17
README.md
Normal 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
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp-log-prepare/type
Normal file
1
etc/s6-overlay/s6-rc.d/myapp-log-prepare/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
||||||
3
etc/s6-overlay/s6-rc.d/myapp-log-prepare/up
Executable file
3
etc/s6-overlay/s6-rc.d/myapp-log-prepare/up
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
if { mkdir -p /var/log/myapp }
|
||||||
|
if { chown nobody:nogroup /var/log/myapp }
|
||||||
|
chmod 02755 /var/log/myapp
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp-log/consumer-for
Normal file
1
etc/s6-overlay/s6-rc.d/myapp-log/consumer-for
Normal file
@ -0,0 +1 @@
|
|||||||
|
myapp
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp-log/pipeline-name
Normal file
1
etc/s6-overlay/s6-rc.d/myapp-log/pipeline-name
Normal file
@ -0,0 +1 @@
|
|||||||
|
myapp-pipeline
|
||||||
2
etc/s6-overlay/s6-rc.d/myapp-log/run
Executable file
2
etc/s6-overlay/s6-rc.d/myapp-log/run
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
exec logutil-service /var/log/myapp
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp-log/type
Normal file
1
etc/s6-overlay/s6-rc.d/myapp-log/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
longrun
|
||||||
0
etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
Normal file
0
etc/s6-overlay/s6-rc.d/myapp/dependencies.d/base
Normal file
9
etc/s6-overlay/s6-rc.d/myapp/finish
Executable file
9
etc/s6-overlay/s6-rc.d/myapp/finish
Executable 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
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp/producer-for
Normal file
1
etc/s6-overlay/s6-rc.d/myapp/producer-for
Normal file
@ -0,0 +1 @@
|
|||||||
|
myapp-log
|
||||||
3
etc/s6-overlay/s6-rc.d/myapp/run
Executable file
3
etc/s6-overlay/s6-rc.d/myapp/run
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/command/with-contenv sh
|
||||||
|
exec 2>&1
|
||||||
|
exec s6-setuidgid daemon /usr/local/bin/myapp
|
||||||
1
etc/s6-overlay/s6-rc.d/myapp/type
Normal file
1
etc/s6-overlay/s6-rc.d/myapp/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
longrun
|
||||||
0
etc/s6-overlay/s6-rc.d/user/contents.d/myapp
Normal file
0
etc/s6-overlay/s6-rc.d/user/contents.d/myapp
Normal file
26
main.go
Normal file
26
main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user