Mastering Docker Job Scheduling with Go: Build Your Own Custom Image For Cron
Hey there, Docker fans! Are you tired of Kubernetes making you feel like a CronJob object—always scheduled and never in charge? And why doesn't Docker include a built-in solution for task scheduling? Sometimes, you just need a simple orchestration tool like Docker Swarm for your itty-bitty project, but then you realize that Docker has left you high and dry without a scheduling lifeline. It's like a chef lacking a knife. But hey, don't panic, you can build your own unique Docker image and take control of your containerized operations thanks to the brilliance of Go and the tried-and-true cron function. So let's hop on and learn as we set out on a trip to truly understand Docker job scheduling.
We're going to create a docker image with a base of an alpine image. Well if you may ask why; it's because the alpine image is small and sweet. Also, we're going to have Go as our script, you may also use python. (sorry python lovers; I'm a huge fan of Go here).
Our script
Our main go script will have an important task to do, which is to tell a silly joke. Here it is:
package main
import "fmt"
func main() {
fmt.Printf("%s\n\n\n", "Why don't scientists trust atoms?")
fmt.Printf("%s\n", "Because they make up everything.")
}
We'll also have four more files to consider:
1. crontab.txt (For us to schedule timing for executing our script): Our task will run every 30 minutes.
2. script.sh (to find and execute our cron service)
3. entry.sh (entry point for our docker image): Our 'crond' service will start running on the foreground daemon (-f parameter) and logging set for 'LOG_DEBUG' with the -l 8 parameter.
4. last but not least: our Dockerfile to make our image and send it to the moon.
All in one script
Here are the files in their respective order:
# ---> crontab.txt file
*/30 * * * * /script.sh
# ---> script.sh file
#!/bin/sh
echo "Running Go script ..."
/usr/src/app/cron-job-service
# ---> entry.sh file
#!/bin/sh
echo "Running service once before starting our cron service ... "
/usr/src/app/cron-job-service
# sleeping for 2 seconds because i love sleeping
sleep 2
echo "Running cron ..."
/usr/sbin/crond -f -l 8
Our Docker file will use a multistage build, the base is a GO alpine image to build our service and the second one is just an alpine image to host our pre-built service.
FROM golang:alpine AS base_alpine
RUN apk add bash ca-certificates git gcc g++ libc-dev
WORKDIR /temp
ADD . /temp
RUN go build -v -o cron-job-service && mkdir /final \
&& cp -r /temp/cron-job-service /final
FROM alpine:3.17
RUN apk update && apk add ca-certificates \
&& rm -rf /var/cache/apk/*
RUN apk add --no-cache --upgrade bash
WORKDIR /usr/src/app
COPY --from=base_alpine /final /usr/src/app/
COPY crontab.txt /crontab.txt
COPY script.sh /script.sh
COPY entry.sh /entry.sh
# setting owners permissions to read, write and excute
RUN chmod 755 /script.sh /entry.sh
RUN /usr/bin/crontab /crontab.txt
CMD ["/entry.sh"]
Finally, your scheduled docker service will tell you the same silly joke every 30 minutes. Isn't that cool?
Source: https://github.com/MerNat/cron-go