mirror of
https://github.com/willfarrell/docker-crontab.git
synced 2025-06-25 21:34:06 +02:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
a4e4227327 | |||
ef29a8dadc | |||
e28e8dbd2f | |||
cba326b800 | |||
16396988c2 | |||
22900fddd1 | |||
ff6fde0e5b | |||
5f5abd5251 | |||
84ce659f86 | |||
92d2c91227 | |||
0ef158253f | |||
af7994a740 | |||
1af64f5f7d | |||
44a4708123 | |||
85a0ecf368 | |||
cdf3f1a005 | |||
e81c5c7fb9 | |||
71b0bf9ac2 | |||
61149875ae | |||
2c633af586 | |||
8940b3300e | |||
6406e1f6e4 | |||
9349a92372 | |||
c82354e261 | |||
21e58d0588 | |||
911eed81f6 | |||
ac1760ce71 | |||
68fa96e2e8 | |||
b0f5681faf | |||
945357ce4a | |||
5d9d345dd5 | |||
5946f3545d | |||
46407e1e27 | |||
e3afe6c3e5 | |||
0a4e3f5753 | |||
71661b4971 | |||
cba3bcb0d0 | |||
02a89f6dac | |||
b89e312569 | |||
f601ca262d | |||
b52842b07a | |||
147e900f8b | |||
40b8b93c2a | |||
d5cfe3bc76 | |||
d5f4764d25 | |||
61ef1db4bf |
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [willfarrell]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
48
.github/workflows/build.yml
vendored
Normal file
48
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
multi:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- if: github.ref == 'refs/heads/main'
|
||||||
|
name: Conditional(Set tag as `latest`)
|
||||||
|
run: echo "tag=willfarrell/crontab:latest" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
name: Conditional(Set tag as `{version}`)
|
||||||
|
run: echo "tag=willfarrell/crontab:${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.tag }}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
|||||||
.idea
|
.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
home_dir
|
|
||||||
config.json
|
config.json
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
FROM library/docker:stable
|
FROM library/docker:stable
|
||||||
|
|
||||||
ENV HOME_DIR=/opt/crontab
|
ENV HOME_DIR=/opt/crontab
|
||||||
RUN apk add --no-cache --virtual .run-deps bash jq \
|
RUN apk add --no-cache --virtual .run-deps gettext bash jq \
|
||||||
&& mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects
|
&& mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects \
|
||||||
|
&& adduser -S docker -D
|
||||||
|
|
||||||
COPY docker-entrypoint /
|
COPY docker-entrypoint /
|
||||||
ENTRYPOINT ["/docker-entrypoint"]
|
ENTRYPOINT ["/docker-entrypoint"]
|
||||||
@ -10,4 +11,4 @@ ENTRYPOINT ["/docker-entrypoint"]
|
|||||||
HEALTHCHECK --interval=5s --timeout=3s \
|
HEALTHCHECK --interval=5s --timeout=3s \
|
||||||
CMD ps aux | grep '[c]rond' || exit 1
|
CMD ps aux | grep '[c]rond' || exit 1
|
||||||
|
|
||||||
CMD ["crond","-f"]
|
CMD ["crond", "-f", "-d", "6", "-c", "/etc/crontabs"]
|
||||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 will Farrell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
26
README.md
26
README.md
@ -5,12 +5,12 @@ A simple wrapper over `docker` to all complex cron job to be run in other contai
|
|||||||
## Supported tags and Dockerfile links
|
## Supported tags and Dockerfile links
|
||||||
|
|
||||||
- [`latest` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/master/Dockerfile)
|
- [`latest` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/master/Dockerfile)
|
||||||
|
- [`0.6.0` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/0.6.0/Dockerfile)
|
||||||
|
|
||||||
[](http://microbadger.com/images/willfarrell/crontab "Get your own version badge on microbadger.com") [](http://microbadger.com/images/willfarrell/crontab "Get your own image badge on microbadger.com")
|
 [](http://microbadger.com/images/willfarrell/crontab "Get your own image badge on microbadger.com")
|
||||||
|
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
Yes, I'm aware of [mcuadros/ofelia](https://github.com/mcuadros/ofelia) (280MB), it was the main inspiration for this project.
|
Yes, I'm aware of [mcuadros/ofelia](https://github.com/mcuadros/ofelia) (~10MB), it was the main inspiration for this project.
|
||||||
A great project, don't get me wrong. It was just missing certain key enterprise features I felt were required to support where docker is heading.
|
A great project, don't get me wrong. It was just missing certain key enterprise features I felt were required to support where docker is heading.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@ -22,9 +22,9 @@ A great project, don't get me wrong. It was just missing certain key enterprise
|
|||||||
- Ability to trigger scripts in other containers on completion cron job using `trigger`.
|
- Ability to trigger scripts in other containers on completion cron job using `trigger`.
|
||||||
|
|
||||||
## Config.json
|
## Config.json
|
||||||
- `name`: Human readable name that will be used as teh job filename. Optional.
|
- `name`: Human readable name that will be used as the job filename. Will be converted into a slug. Optional.
|
||||||
- `comment`: Comments to be included with crontab entry. Optional.
|
- `comment`: Comments to be included with crontab entry. Optional.
|
||||||
- `schedule`: Crontab schedule syntax as described in https://godoc.org/github.com/robfig/cron. Ex `@hourly`, `@every 1h30m`, `* * * * * *`. Required.
|
- `schedule`: Crontab schedule syntax as described in https://en.wikipedia.org/wiki/Cron. Ex `@hourly`, `@every 1h30m`, `* * * * *`. Required.
|
||||||
- `command`: Command to be run on in crontab container or docker container/image. Required.
|
- `command`: Command to be run on in crontab container or docker container/image. Required.
|
||||||
- `image`: Docker images name (ex `library/alpine:3.5`). Optional.
|
- `image`: Docker images name (ex `library/alpine:3.5`). Optional.
|
||||||
- `project`: Docker Compose/Swarm project name. Optional, only applies when `contain` is included.
|
- `project`: Docker Compose/Swarm project name. Optional, only applies when `contain` is included.
|
||||||
@ -57,6 +57,7 @@ See [`config.sample.json`](https://github.com/willfarrell/docker-crontab/blob/ma
|
|||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
### Command Line
|
### Command Line
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t crontab .
|
docker build -t crontab .
|
||||||
docker run -d \
|
docker run -d \
|
||||||
@ -67,7 +68,19 @@ docker run -d \
|
|||||||
crontab
|
crontab
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Use with docker-compose
|
||||||
|
|
||||||
|
1. Figure out which network name used for your docker-compose containers
|
||||||
|
* use `docker network ls` to see existing networks
|
||||||
|
* if your `docker-compose.yml` is in `my_dir` directory, you probably has network `my_dir_default`
|
||||||
|
* otherwise [read the docker-compose docs](https://docs.docker.com/compose/networking/)
|
||||||
|
2. Add `dockerargs` to your docker-crontab `config.json`
|
||||||
|
* use `--network NETWORK_NAME` to connect new container into docker-compose network
|
||||||
|
* use `--rm --name NAME` to use named container
|
||||||
|
* e.g. `"dockerargs": "--network my_dir_default --rm --name my-best-cron-job"`
|
||||||
|
|
||||||
### Dockerfile
|
### Dockerfile
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM willfarrell/crontab
|
FROM willfarrell/crontab
|
||||||
|
|
||||||
@ -76,6 +89,7 @@ COPY config.json ${HOME_DIR}/
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Logrotate Dockerfile
|
### Logrotate Dockerfile
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM willfarrell/crontab
|
FROM willfarrell/crontab
|
||||||
|
|
||||||
@ -87,13 +101,13 @@ CMD ["crond", "-f"]
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Logging - In Dev
|
### Logging - In Dev
|
||||||
|
|
||||||
All `stdout` is captured, formatted, and saved to `/var/log/crontab/jobs.log`. Set `LOG_FILE` to `/dev/null` to disable logging.
|
All `stdout` is captured, formatted, and saved to `/var/log/crontab/jobs.log`. Set `LOG_FILE` to `/dev/null` to disable logging.
|
||||||
|
|
||||||
example: `e6ced859-1563-493b-b1b1-5a190b29e938 2017-06-18T01:27:10+0000 [info] Start Cronjob **map-a-vol** map a volume`
|
example: `e6ced859-1563-493b-b1b1-5a190b29e938 2017-06-18T01:27:10+0000 [info] Start Cronjob **map-a-vol** map a volume`
|
||||||
|
|
||||||
grok: `CRONTABLOG %{DATA:request_id} %{TIMESTAMP_ISO8601:timestamp} \[%{LOGLEVEL:severity}\] %{GREEDYDATA:message}`
|
grok: `CRONTABLOG %{DATA:request_id} %{TIMESTAMP_ISO8601:timestamp} \[%{LOGLEVEL:severity}\] %{GREEDYDATA:message}`
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
- [ ] Have ability to auto regenerate crontab on file change (signal HUP?)
|
- [ ] Have ability to auto regenerate crontab on file change (signal HUP?)
|
||||||
- [ ] Run commands on host machine (w/ --privileged?)
|
- [ ] Run commands on host machine (w/ --privileged?)
|
||||||
|
@ -12,4 +12,4 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||||
# - "/usr/bin/docker:/usr/bin/docker:ro"
|
# - "/usr/bin/docker:/usr/bin/docker:ro"
|
||||||
- "/Users/willfarrell/Development/docker/docker-crontab/home_dir:/opt/crontab:rw"
|
- "/Users/willfarrell/Development/docker/docker-crontab/config.json:/opt/crontab/config.json:rw"
|
||||||
|
@ -12,7 +12,7 @@ if [ "${LOG_FILE}" == "" ]; then
|
|||||||
LOG_DIR=/var/log/crontab
|
LOG_DIR=/var/log/crontab
|
||||||
LOG_FILE=${LOG_DIR}/jobs.log
|
LOG_FILE=${LOG_DIR}/jobs.log
|
||||||
mkdir -p ${LOG_DIR}
|
mkdir -p ${LOG_DIR}
|
||||||
touch ${LOG_FILE}
|
touch ${LOG_FILE}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CONFIG=${HOME_DIR}/config.json
|
CONFIG=${HOME_DIR}/config.json
|
||||||
@ -22,11 +22,35 @@ CRONTAB_FILE=/etc/crontabs/docker
|
|||||||
# Ensure dir exist - in case of volume mapping
|
# Ensure dir exist - in case of volume mapping
|
||||||
mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects
|
mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects
|
||||||
|
|
||||||
|
ensure_docker_socket_accessible() {
|
||||||
|
if ! grep -q "^docker:" /etc/group; then
|
||||||
|
# Ensure 'docker' user has permissions for docker socket (without changing permissions)
|
||||||
|
DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCK})
|
||||||
|
if [ "${DOCKER_GID}" != "0" ]; then
|
||||||
|
if ! grep -qE "^[^:]+:[^:]+:${DOCKER_GID}:" /etc/group; then
|
||||||
|
# No group with such gid exists - create group docker
|
||||||
|
addgroup -g ${DOCKER_GID} docker
|
||||||
|
adduser docker docker
|
||||||
|
else
|
||||||
|
# Group with such gid exists - add user "docker" to this group
|
||||||
|
DOCKER_GROUP_NAME=`getent group "${DOCKER_GID}" | awk -F':' '{{ print $1 }}'`
|
||||||
|
adduser docker $DOCKER_GROUP_NAME
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Docker socket belongs to "root" group - add user "docker" to this group
|
||||||
|
adduser docker root
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
slugify() {
|
||||||
|
echo "$@" | iconv -t ascii | sed -r s/[~\^]+//g | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | tr A-Z a-z
|
||||||
|
}
|
||||||
|
|
||||||
make_image_cmd() {
|
make_image_cmd() {
|
||||||
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
|
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
|
||||||
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
|
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
|
||||||
IMAGE=$(echo ${1} | jq -r .image)
|
IMAGE=$(echo ${1} | jq -r .image | envsubst)
|
||||||
TMP_COMMAND=$(echo ${1} | jq -r .command)
|
TMP_COMMAND=$(echo ${1} | jq -r .command)
|
||||||
echo "docker run ${DOCKERARGS} ${IMAGE} ${TMP_COMMAND}"
|
echo "docker run ${DOCKERARGS} ${IMAGE} ${TMP_COMMAND}"
|
||||||
}
|
}
|
||||||
@ -35,8 +59,9 @@ make_container_cmd() {
|
|||||||
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
|
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
|
||||||
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
|
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
|
||||||
SCRIPT_NAME=$(echo ${1} | jq -r .name)
|
SCRIPT_NAME=$(echo ${1} | jq -r .name)
|
||||||
|
SCRIPT_NAME=$(slugify $SCRIPT_NAME)
|
||||||
PROJECT=$(echo ${1} | jq -r .project)
|
PROJECT=$(echo ${1} | jq -r .project)
|
||||||
CONTAINER=$(echo ${1} | jq -r .container)
|
CONTAINER=$(echo ${1} | jq -r .container | envsubst)
|
||||||
TMP_COMMAND=$(echo ${1} | jq -r .command)
|
TMP_COMMAND=$(echo ${1} | jq -r .command)
|
||||||
|
|
||||||
if [ "${PROJECT}" != "null" ]; then
|
if [ "${PROJECT}" != "null" ]; then
|
||||||
@ -81,25 +106,25 @@ make_cmd() {
|
|||||||
parse_schedule() {
|
parse_schedule() {
|
||||||
case $1 in
|
case $1 in
|
||||||
"@yearly")
|
"@yearly")
|
||||||
echo "0 0 0 1 1 *"
|
echo "0 0 1 1 *"
|
||||||
;;
|
;;
|
||||||
"@annually")
|
"@annually")
|
||||||
echo "0 0 0 1 1 *"
|
echo "0 0 1 1 *"
|
||||||
;;
|
;;
|
||||||
"@monthly")
|
"@monthly")
|
||||||
echo "0 0 0 1 * *"
|
echo "0 0 1 * *"
|
||||||
;;
|
;;
|
||||||
"@weekly")
|
"@weekly")
|
||||||
echo "0 0 0 * * 0"
|
echo "0 0 * * 0"
|
||||||
;;
|
;;
|
||||||
"@daily")
|
"@daily")
|
||||||
echo "0 0 0 * * *"
|
echo "0 0 * * *"
|
||||||
;;
|
;;
|
||||||
"@midnight")
|
"@midnight")
|
||||||
echo "0 0 0 * * *"
|
echo "0 0 * * *"
|
||||||
;;
|
;;
|
||||||
"@hourly")
|
"@hourly")
|
||||||
echo "0 0 * * * *"
|
echo "0 * * * *"
|
||||||
;;
|
;;
|
||||||
"@every")
|
"@every")
|
||||||
TIME=$2
|
TIME=$2
|
||||||
@ -119,7 +144,7 @@ parse_schedule() {
|
|||||||
TOTAL=$(($TOTAL + ${D::-1} * 60 * 24))
|
TOTAL=$(($TOTAL + ${D::-1} * 60 * 24))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "*/${TOTAL} * * * * *"
|
echo "*/${TOTAL} * * * *"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "${@}"
|
echo "${@}"
|
||||||
@ -151,6 +176,7 @@ function build_crontab() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
SCRIPT_NAME=$(jq -r .[$i].name ${CONFIG})
|
SCRIPT_NAME=$(jq -r .[$i].name ${CONFIG})
|
||||||
|
SCRIPT_NAME=$(slugify $SCRIPT_NAME)
|
||||||
if [ "${SCRIPT_NAME}" == "null" ]; then
|
if [ "${SCRIPT_NAME}" == "null" ]; then
|
||||||
SCRIPT_NAME=$(cat /proc/sys/kernel/random/uuid)
|
SCRIPT_NAME=$(cat /proc/sys/kernel/random/uuid)
|
||||||
fi
|
fi
|
||||||
@ -204,6 +230,8 @@ EOF
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_docker_socket_accessible
|
||||||
|
|
||||||
if [ "$1" = "crond" ]; then
|
if [ "$1" = "crond" ]; then
|
||||||
if [ -f ${CONFIG} ]; then
|
if [ -f ${CONFIG} ]; then
|
||||||
build_crontab
|
build_crontab
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# This file is for testing the logging of docker output #8
|
||||||
|
|
||||||
LOG_FILE=./jobs.log
|
LOG_FILE=./jobs.log
|
||||||
touch ${LOG_FILE}
|
touch ${LOG_FILE}
|
||||||
UUID="xxxxxxxxxxxxxxxxx"
|
UUID="xxxxxxxxxxxxxxxxx"
|
Reference in New Issue
Block a user