Compare commits

...

59 Commits
0.2.0 ... main

Author SHA1 Message Date
will Farrell
be97512ec2
ci: kiss 2020-12-26 18:18:02 -07:00
will Farrell
89cf941fea
ci: only allow supproted by docker 2020-12-26 18:13:22 -07:00
will Farrell
5611ac5014
ci: try with all platforms 2020-12-26 17:59:12 -07:00
will Farrell
b29a6bb3b3
ci: remove platform list 2020-12-26 17:55:52 -07:00
will Farrell
c2331fc9e7
Merge pull request #40 from chiqomar/master
Adding python conversion for TOML and YAML
2020-12-26 17:45:46 -07:00
Omar Ahmad
88bed2bc4a Fixing entrypoint dealing with JSON mapping 2020-12-23 13:22:15 -05:00
Omar Ahmad
0ef54cc06b Updating README, adding JSON mapping support for consistency 2020-12-23 13:08:05 -05:00
will Farrell
d9b4cecea0
ci: remove unsupported 2020-12-22 16:33:24 -07:00
will Farrell
e55dba16d7
ci: build all platforms 2020-12-22 15:21:41 -07:00
Omar Ahmad
18e9954d74 Using RQ to change toml and yaml to JSON, removing all python stuff 2020-12-21 19:19:52 -05:00
Omar Ahmad
b9bbeacae1 Merge branch 'main' of github.com:willfarrell/docker-crontab 2020-12-08 16:50:33 -05:00
will Farrell
a4e4227327
doc: clean up 2020-12-02 13:22:35 -07:00
will Farrell
ef29a8dadc
ci: build on all tags 2020-12-02 13:18:01 -07:00
will Farrell
e28e8dbd2f
docs: bump version 2020-12-02 13:16:14 -07:00
will Farrell
cba326b800
ci: remove platform list 2020-12-02 12:54:34 -07:00
will Farrell
16396988c2
ci: fix typo 2020-12-02 12:49:55 -07:00
will Farrell
22900fddd1
ci: extra logging 2020-12-02 12:47:50 -07:00
will Farrell
ff6fde0e5b
ci: echo tag value 2020-12-02 12:41:45 -07:00
will Farrell
5f5abd5251
ci: fix typo 2020-12-02 12:01:31 -07:00
will Farrell
84ce659f86
ci: change how tag is built 2020-12-02 11:50:10 -07:00
will Farrell
92d2c91227
ci: force expression tag 2020-12-02 11:45:32 -07:00
will Farrell
0ef158253f
ci: fix str 2020-12-02 11:43:12 -07:00
will Farrell
af7994a740
ci: fix how tag is built 2020-12-02 11:42:08 -07:00
will Farrell
1af64f5f7d
ci: log env 2020-12-02 11:39:27 -07:00
will Farrell
44a4708123
ci: change how env is set 2020-12-02 11:35:28 -07:00
will Farrell
85a0ecf368
ci: ensure push always happens 2020-12-02 11:32:39 -07:00
will Farrell
cdf3f1a005
docs: update tag versions 2020-12-02 11:31:16 -07:00
will Farrell
e81c5c7fb9
ci: fix docker login 2020-12-02 11:26:30 -07:00
will Farrell
71b0bf9ac2
ci: fix eq operator 2020-12-02 11:23:41 -07:00
will Farrell
61149875ae
ci: fix expression 2020-12-02 11:22:09 -07:00
will Farrell
2c633af586
ci: syntax fix 2020-12-02 11:20:25 -07:00
will Farrell
8940b3300e
ci: add in build process 2020-12-02 11:18:46 -07:00
will Farrell
6406e1f6e4
docs: add docker pull count 2020-12-01 17:34:27 -07:00
will Farrell
9349a92372
docs: add funcing 2020-11-30 22:41:56 -07:00
will Farrell
c82354e261
Merge pull request #29 from martinec/patch-1
Update README.md
2020-02-26 12:33:12 -07:00
Omar Ahmad
200cd1313f Adding gitignore 2020-01-09 12:46:37 -05:00
Omar Ahmad
5013ecbc3f Adding vscode to gitignore 2019-09-13 16:25:07 -04:00
Omar Ahmad
4f9146b8f8 using tini, functions for most code in entrypoint 2019-09-03 13:15:31 -04:00
Omar Ahmad
4a0d85f51a Adding python conversion for TOML and YAML; slightly more verbose syntax for dockerargs 2019-08-15 10:52:20 -04:00
will Farrell
21e58d0588
feat: add license 2019-08-04 17:10:47 -06:00
Cristian Martinez
911eed81f6
Update README.md
The final Ofelia image has now a size of ~10MB

@see https://github.com/mcuadros/ofelia/pull/20
2019-03-27 14:28:48 +01:00
will Farrell
ac1760ce71
Merge pull request #27 from sergey-shambir/docs-for-docker-compose-use-case
Documented usage with docker-compose
2019-03-17 13:10:49 -06:00
will Farrell
68fa96e2e8
Merge pull request #25 from sergey-shambir/issue_20
Use another way to ensure docker socket is accessible
2019-03-17 13:10:08 -06:00
will Farrell
b0f5681faf
Merge pull request #26 from sergey-shambir/docker-cmd-fix
Improve crond command in Dockerfile
2019-03-17 13:09:12 -06:00
will Farrell
945357ce4a
Merge pull request #24 from sergey-shambir/envsubst
Added support for envsubst in image/container name
2019-03-17 13:08:19 -06:00
will Farrell
5d9d345dd5
Merge pull request #23 from iusmac/patch-1
Fix issue "ambiguous redirect"
2019-03-04 09:21:45 -07:00
Sergey Shambir
5946f3545d Documented usage with docker-compose 2019-03-02 16:16:07 +03:00
Sergey Shambir
46407e1e27 Turned off verbose logging
For busybox cron level 6 is enough to see errors and hide debug info
Debug info shown at level 5
Nothing shown at levels 0, 1, 2, 3, 4
See https://unix.stackexchange.com/questions/412805/crond-log-level-meaning
2019-03-02 16:02:57 +03:00
Sergey Shambir
e3afe6c3e5 Fix crond command in Dockerfile
- added logging to docker logs
- run with /etc/crontabs dir
See also https://unix.stackexchange.com/questions/412805/crond-log-level-meaning
2019-03-02 16:02:52 +03:00
Sergey Shambir
0a4e3f5753 Use another way to ensure docker socket is accessible
- check if socket group ID is presented in /etc/group
- if presented, just add 'docker' user to this group
- if not, create 'docker' group and add 'docker' user to this group
Fixes issue #20
2019-03-02 16:01:40 +03:00
Sergey Shambir
71661b4971 Added support for envsubst in image/container name
Envsubst allows to use dynamic container name
We use image name env substitution with docker-compose and .env to select right image tag for local development
Within alpine, envsubst installed with gettext package.
2019-03-02 15:49:26 +03:00
iusmac
cba3bcb0d0
Fix issue "ambiguous redirect"
Full error message: "/docker-entrypoint.sh: line 58: ${HOME_DIR}/projects/${SCRIPT_NAME}.sh: ambiguous redirect"

The error appears when in Config.json is present `name` and `container`.
2019-03-01 20:50:12 +01:00
will Farrell
02a89f6dac fix: clean up logic and only apply group if needed 2018-06-30 15:23:27 -06:00
will Farrell
b89e312569
fix: Change group id
Change group id to not conflict with host common id

Fix #13
2018-02-27 23:44:47 -07:00
will Farrell
f601ca262d
Merge pull request #11 from kendokan/master
fixed failure if docker group already existed
2018-01-11 09:15:18 -07:00
kendokan
b52842b07a
fixed failure if docker group already existed
This error prevents the container from restarting.
2018-01-11 08:13:11 -08:00
will Farrell
147e900f8b
Merge pull request #10 from kendokan/master
fixed https://github.com/willfarrell/docker-crontab/issues/9
2018-01-09 20:16:50 -07:00
Doug Dimick
40b8b93c2a fixed https://github.com/willfarrell/docker-crontab/issues/9 2018-01-09 13:17:49 -08:00
will Farrell
d5cfe3bc76 #6 Added adduser to the build script 2017-11-14 14:04:30 -07:00
15 changed files with 451 additions and 72 deletions

12
.github/FUNDING.yml vendored Normal file
View 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']

49
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,49 @@
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
id: 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 }}

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
*.iml
config.json
.vscode
.DS_Store

View File

@ -1,13 +1,26 @@
FROM alpine:3.12 as rq-build
ENV RQ_VERSION=1.0.2
WORKDIR /root/
RUN apk --update add upx \
&& wget https://github.com/dflemstr/rq/releases/download/v${RQ_VERSION}/rq-v${RQ_VERSION}-x86_64-unknown-linux-musl.tar.gz \
&& tar -xvf rq-v1.0.2-x86_64-unknown-linux-musl.tar.gz \
&& upx --brute rq
FROM library/docker:stable
COPY --from=rq-build /root/rq /usr/local/bin
ENV HOME_DIR=/opt/crontab
RUN apk add --no-cache --virtual .run-deps bash jq \
&& mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects
RUN apk add --no-cache --virtual .run-deps gettext jq bash tini \
&& mkdir -p ${HOME_DIR}/jobs ${HOME_DIR}/projects \
&& adduser -S docker -D
COPY docker-entrypoint /
ENTRYPOINT ["/docker-entrypoint"]
ENTRYPOINT ["/sbin/tini", "--", "/docker-entrypoint"]
HEALTHCHECK --interval=5s --timeout=3s \
CMD ps aux | grep '[c]rond' || exit 1
CMD ["crond","-f"]
CMD ["crond", "-f", "-d", "6", "-c", "/etc/crontabs"]

21
LICENSE Normal file
View 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.

View File

@ -5,12 +5,13 @@ A simple wrapper over `docker` to all complex cron job to be run in other contai
## Supported tags and Dockerfile links
- [`latest` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/master/Dockerfile)
- [`1.0.0` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/1.0.0/Dockerfile)
- [`0.6.0` (*Dockerfile*)](https://github.com/willfarrell/docker-crontab/blob/0.6.0/Dockerfile)
[![](https://images.microbadger.com/badges/version/willfarrell/crontab.svg)](http://microbadger.com/images/willfarrell/crontab "Get your own version badge on microbadger.com") [![](https://images.microbadger.com/badges/image/willfarrell/crontab.svg)](http://microbadger.com/images/willfarrell/crontab "Get your own image badge on microbadger.com")
![](https://img.shields.io/docker/pulls/willfarrell/crontab "Total docker pulls") [![](https://images.microbadger.com/badges/image/willfarrell/crontab.svg)](http://microbadger.com/images/willfarrell/crontab "Get your own image badge on microbadger.com")
## 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) (>250MB when this was created), 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.
## Features
@ -21,7 +22,10 @@ A great project, don't get me wrong. It was just missing certain key enterprise
- Run command on a instances of a scaled container using `project`.
- Ability to trigger scripts in other containers on completion cron job using `trigger`.
## Config.json
## Config file
The config file can be specifed in any of `json`, `toml`, or `yaml`, and can be defined as either an array or mapping (top-level keys will be ignored; can be useful for organizing commands)
- `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.
- `schedule`: Crontab schedule syntax as described in https://en.wikipedia.org/wiki/Cron. Ex `@hourly`, `@every 1h30m`, `* * * * *`. Required.
@ -33,7 +37,7 @@ A great project, don't get me wrong. It was just missing certain key enterprise
- `trigger`: Array of docker-crontab subset objects. Subset includes: `image`,`project`,`container`,`command`,`dockerargs`
- `onstart`: Run the command on `crontab` container start, set to `true`. Optional, defaults to falsey.
See [`config.sample.json`](https://github.com/willfarrell/docker-crontab/blob/master/config.sample.json) for examples.
See [`config-samples`](config-samples) for examples.
```json
[{
@ -57,6 +61,7 @@ See [`config.sample.json`](https://github.com/willfarrell/docker-crontab/blob/ma
## How to use
### Command Line
```bash
docker build -t crontab .
docker run -d \
@ -67,7 +72,19 @@ docker run -d \
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
FROM willfarrell/crontab
@ -76,6 +93,7 @@ COPY config.json ${HOME_DIR}/
```
### Logrotate Dockerfile
```Dockerfile
FROM willfarrell/crontab
@ -87,13 +105,13 @@ CMD ["crond", "-f"]
```
### 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.
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}`
## TODO
- [ ] Have ability to auto regenerate crontab on file change (signal HUP?)
- [ ] Run commands on host machine (w/ --privileged?)

View File

@ -0,0 +1,60 @@
[
{
"comment": "cron with triggered commands",
"schedule": "* * * * *",
"command": "echo hello",
"project": "crontab",
"container": "myapp",
"trigger": [
{
"command": "echo world",
"container": "crontab_myapp_1"
}
]
},
{
"comment": "map a volume",
"schedule": "* * * * *",
"dockerargs": "-d -v /tmp:/tmp",
"command": "echo new",
"image": "alpine:3.5"
},
{
"comment": "use an ENV from inside a container",
"schedule": "@hourly",
"dockerargs": "-d -e FOO=BAR",
"command": "sh -c 'echo hourly ${FOO}'",
"image": "alpine:3.5"
},
{
"comment": "trigger every 2 min",
"schedule": "@every 2m",
"command": "echo 2 minute",
"image": "alpine:3.5",
"trigger": [
{
"command": "echo world",
"container": "crontab_myapp_1"
}
]
},
{
"schedule": "*/5 * * * *",
"command": "/usr/sbin/logrotate /etc/logrotate.conf"
},
{
"comment": "Regenerate Certificate then reload nginx",
"schedule": "43 6,18 * * *",
"command": "sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge dns-01 --hook dehydrated-dns'",
"dockerargs": "--env-file /opt/crontab/env/letsencrypt.env -v webapp_nginx_tls_cert:/etc/ssl -v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge",
"image": "willfarrell/letsencrypt",
"trigger": [
{
"command": "sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t && /usr/sbin/nginx -s reload'",
"project": "conduit",
"container": "nginx"
}
],
"onstart": true
}
]

View File

@ -0,0 +1,50 @@
{
"cron with triggered commands": {
"comment": "cron with triggered commands",
"schedule": "* * * * *",
"command": "echo hello",
"project": "crontab",
"container": "myapp",
"trigger": [{ "command": "echo world", "container": "crontab_myapp_1" }]
},
"map a volume": {
"comment": "map a volume",
"schedule": "* * * * *",
"dockerargs": "-d -v /tmp:/tmp",
"command": "echo new",
"image": "alpine:3.5"
},
"use an ENV from inside a container": {
"comment": "use an ENV from inside a container",
"schedule": "@hourly",
"dockerargs": "-d -e FOO=BAR",
"command": "sh -c 'echo hourly ${FOO}'",
"image": "alpine:3.5"
},
"trigger every 2 min": {
"comment": "trigger every 2 min",
"schedule": "@every 2m",
"command": "echo 2 minute",
"image": "alpine:3.5",
"trigger": [{ "command": "echo world", "container": "crontab_myapp_1" }]
},
"null": {
"schedule": "*/5 * * * *",
"command": "/usr/sbin/logrotate /etc/logrotate.conf"
},
"Regenerate Certificate then reload nginx": {
"comment": "Regenerate Certificate then reload nginx",
"schedule": "43 6,18 * * *",
"command": "sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge dns-01 --hook dehydrated-dns'",
"dockerargs": "--env-file /opt/crontab/env/letsencrypt.env -v webapp_nginx_tls_cert:/etc/ssl -v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge",
"image": "willfarrell/letsencrypt",
"trigger": [
{
"command": "sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t && /usr/sbin/nginx -s reload'",
"project": "conduit",
"container": "nginx"
}
],
"onstart": true
}
}

View File

@ -0,0 +1,46 @@
cron with triggered commands:
command: echo hello
comment: cron with triggered commands
container: myapp
project: crontab
schedule: '* * * * *'
trigger:
- command: echo world
container: crontab_myapp_1
map a volume:
command: echo new
comment: map a volume
dockerargs: -d -v /tmp:/tmp
image: alpine:3.5
schedule: '* * * * *'
use an ENV from inside a container:
command: sh -c 'echo hourly ${FOO}'
comment: use an ENV from inside a container
dockerargs: -d -e FOO=BAR
image: alpine:3.5
schedule: '@hourly'
trigger every 2 min:
command: echo 2 minute
comment: trigger every 2 min
image: alpine:3.5
schedule: '@every 2m'
trigger:
- command: echo world
container: crontab_myapp_1
null:
command: /usr/sbin/logrotate /etc/logrotate.conf
schedule: '*/5 * * * *'
Regenerate Certificate then reload nginx:
command: sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge
dns-01 --hook dehydrated-dns'
comment: Regenerate Certificate then reload nginx
dockerargs: --env-file /opt/crontab/env/letsencrypt.env -v webapp_nginx_tls_cert:/etc/ssl
-v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge
image: willfarrell/letsencrypt
onstart: true
schedule: 43 6,18 * * *
trigger:
- command: sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t &&
/usr/sbin/nginx -s reload'
container: nginx
project: conduit

View File

@ -0,0 +1,50 @@
# toml files can only have top-loevl mappings, so this is the only sample
["cron with triggered commands"]
comment = "cron with triggered commands"
schedule = "* * * * *"
command = "echo hello"
project = "crontab"
container = "myapp"
[["cron with triggered commands".trigger]]
command = "echo world"
container = "crontab_myapp_1"
["map a volume"]
comment = "map a volume"
schedule = "* * * * *"
dockerargs = "-d -v /tmp:/tmp"
command = "echo new"
image = "alpine:3.5"
["use an ENV from inside a container"]
comment = "use an ENV from inside a container"
schedule = "@hourly"
dockerargs = "-d -e FOO=BAR"
command = "sh -c 'echo hourly ${FOO}'"
image = "alpine:3.5"
["trigger every 2 min"]
comment = "trigger every 2 min"
schedule = "@every 2m"
command = "echo 2 minute"
image = "alpine:3.5"
[["trigger every 2 min".trigger]]
command = "echo world"
container = "crontab_myapp_1"
["? /usr/sbin/logrotate /etc/logrotate.conf*/5 * * * *"]
schedule = "*/5 * * * *"
command = "/usr/sbin/logrotate /etc/logrotate.conf"
["Regenerate Certificate then reload nginx"]
comment = "Regenerate Certificate then reload nginx"
schedule = "43 6,18 * * *"
command = "sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge dns-01 --hook dehydrated-dns'"
dockerargs = "--env-file /opt/crontab/env/letsencrypt.env -v ${PWD}:/etc/ssl -v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge"
image = "willfarrell/letsencrypt"
onstart = true
[["Regenerate Certificate then reload nginx".trigger]]
command = "sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t && /usr/sbin/nginx -s reload'"
project = "conduit"
container = "nginx"

View File

@ -0,0 +1,40 @@
- command: echo hello
comment: cron with triggered commands
container: myapp
project: crontab
schedule: '* * * * *'
trigger:
- command: echo world
container: crontab_myapp_1
- command: echo new
comment: map a volume
dockerargs: -d -v /tmp:/tmp
image: alpine:3.5
schedule: '* * * * *'
- command: sh -c 'echo hourly ${FOO}'
comment: use an ENV from inside a container
dockerargs: -d -e FOO=BAR
image: alpine:3.5
schedule: '@hourly'
- command: echo 2 minute
comment: trigger every 2 min
image: alpine:3.5
schedule: '@every 2m'
trigger:
- command: echo world
container: crontab_myapp_1
- command: /usr/sbin/logrotate /etc/logrotate.conf
schedule: '*/5 * * * *'
- command: sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge
dns-01 --hook dehydrated-dns'
comment: Regenerate Certificate then reload nginx
dockerargs: --env-file /opt/crontab/env/letsencrypt.env -v webapp_nginx_tls_cert:/etc/ssl
-v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge
image: willfarrell/letsencrypt
onstart: true
schedule: 43 6,18 * * *
trigger:
- command: sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t &&
/usr/sbin/nginx -s reload'
container: nginx
project: conduit

View File

@ -1,47 +0,0 @@
[{
"comment":"cron with triggered commands",
"schedule":"* * * * *",
"command":"echo hello",
"project":"crontab",
"container":"myapp",
"trigger":[{
"command":"echo world",
"container":"crontab_myapp_1"
}]
},{
"comment":"map a volume",
"schedule":"* * * * *",
"dockerargs":"-d -v /tmp:/tmp",
"command":"echo new",
"image":"alpine:3.5"
},{
"comment":"use an ENV from inside a container",
"schedule":"@hourly",
"dockerargs":"-d -e FOO=BAR",
"command":"sh -c 'echo hourly ${FOO}'",
"image":"alpine:3.5"
},{
"comment":"trigger every 2 min",
"schedule":"@every 2m",
"command":"echo 2 minute",
"image":"alpine:3.5",
"trigger":[{
"command":"echo world",
"container":"crontab_myapp_1"
}]
},{
"schedule":"*/5 * * * *",
"command":"/usr/sbin/logrotate /etc/logrotate.conf"
},{
"comment":"Regenerate Certificate then reload nginx",
"schedule":"43 6,18 * * *",
"command":"sh -c 'dehydrated --cron --out /etc/ssl --domain ${LE_DOMAIN} --challenge dns-01 --hook dehydrated-dns'",
"dockerargs":"--env-file /opt/crontab/env/letsencrypt.env -v webapp_nginx_tls_cert:/etc/ssl -v webapp_nginx_acme_challenge:/var/www/.well-known/acme-challenge",
"image":"willfarrell/letsencrypt",
"trigger":[{
"command":"sh -c '/etc/scripts/make_hpkp ${NGINX_DOMAIN} && /usr/sbin/nginx -t && /usr/sbin/nginx -s reload'",
"project":"conduit",
"container":"nginx"
}],
"onstart":true
}]

View File

@ -11,5 +11,4 @@ services:
restart: always
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
# - "/usr/bin/docker:/usr/bin/docker:ro"
- "/Users/willfarrell/Development/docker/docker-crontab/config.json:/opt/crontab/config.json:rw"
- "${PWD}/config-samples/config.sample.mapping.json:/opt/crontab/config.json:rw"

View File

@ -12,24 +12,71 @@ if [ "${LOG_FILE}" == "" ]; then
LOG_DIR=/var/log/crontab
LOG_FILE=${LOG_DIR}/jobs.log
mkdir -p ${LOG_DIR}
touch ${LOG_FILE}
touch ${LOG_FILE}
fi
CONFIG=${HOME_DIR}/config.json
get_config() {
if [ -f "${HOME_DIR}/config.json" ]; then
jq 'map(.)' ${HOME_DIR}/config.json > ${HOME_DIR}/config.working.json
elif [ -f "${HOME_DIR}/config.toml" ]; then
rq -t <<< $(cat ${HOME_DIR}/config.toml) | jq 'map(.)' > ${HOME_DIR}/config.json
elif [ -f "${HOME_DIR}/config.yml" ]; then
rq -y <<< $(cat ${HOME_DIR}/config.yml) | jq 'map(.)' > ${HOME_DIR}/config.json
elif [ -f "${HOME_DIR}/config.yaml" ]; then
rq -y <<< $(cat ${HOME_DIR}/config.yaml) | jq 'map(.)' > ${HOME_DIR}/config.json
fi
}
DOCKER_SOCK=/var/run/docker.sock
CRONTAB_FILE=/etc/crontabs/docker
# Ensure dir exist - in case of volume mapping
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() {
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
VOLUMES=$(echo ${1} | jq -r '.volumes | map(" -v " + .) | join("")')
PORTS=$(echo ${1} | jq -r '.ports | map(" -p " + .) | join("")')
EXPOSE=$(echo ${1} | jq -r '.expose | map(" --expose " + .) | join("")')
# We'll add name in, if it exists
NAME=$(echo ${1} | jq -r 'select(.name != null) | .name')
NETWORK=$(echo ${1} | jq -r 'select(.network != null) | .network')
ENVIRONMENT=$(echo ${1} | jq -r '.environment | map(" -e " + .) | join("")')
# echo ${1} | jq -r '.environment | join("\n")' > ${PWD}/${NAME}.env
# ENVIRONMENT=" --env-file ${PWD}/${NAME}.env"
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
IMAGE=$(echo ${1} | jq -r .image)
if [ ! -z "${NAME}" ]; then DOCKERARGS="${DOCKERARGS} --rm --name ${NAME} "; fi
if [ ! -z "${NETWORK}" ]; then DOCKERARGS="${DOCKERARGS} --network ${NETWORK} "; fi
if [ ! -z "${VOLUMES}" ]; then DOCKERARGS="${DOCKERARGS}${VOLUMES}"; fi
if [ ! -z "${ENVIRONMENT}" ]; then DOCKERARGS="${DOCKERARGS}${ENVIRONMENT}"; fi
if [ ! -z "${PORTS}" ]; then DOCKERARGS="${DOCKERARGS}${PORTS}"; fi
if [ ! -z "${EXPOSE}" ]; then DOCKERARGS="${DOCKERARGS}${EXPOSE}"; fi
IMAGE=$(echo ${1} | jq -r .image | envsubst)
TMP_COMMAND=$(echo ${1} | jq -r .command)
echo "docker run ${DOCKERARGS} ${IMAGE} ${TMP_COMMAND}"
}
@ -38,8 +85,9 @@ make_container_cmd() {
DOCKERARGS=$(echo ${1} | jq -r .dockerargs)
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
SCRIPT_NAME=$(echo ${1} | jq -r .name)
SCRIPT_NAME=$(slugify $SCRIPT_NAME)
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)
if [ "${PROJECT}" != "null" ]; then
@ -58,6 +106,7 @@ for CONTAINER_NAME in \$CONTAINERS; do
done
EOF
echo "/bin/bash ${HOME_DIR}/projects/${SCRIPT_NAME}.sh"
# cat "/bin/bash ${HOME_DIR}/projects/${SCRIPT_NAME}.sh"
else
echo "docker exec ${DOCKERARGS} ${CONTAINER} ${TMP_COMMAND}"
fi
@ -131,6 +180,7 @@ parse_schedule() {
}
function build_crontab() {
rm -rf ${CRONTAB_FILE}
ONSTART=()
@ -208,13 +258,27 @@ EOF
done
}
if [ "$1" = "crond" ]; then
if [ -f ${CONFIG} ]; then
build_crontab
else
echo "Unable to find ${HOME_DIR}/config.json"
fi
fi
echo "$@"
exec "$@"
ensure_docker_socket_accessible
start_app() {
get_config
if [ -f "${HOME_DIR}/config.working.json" ]; then
export CONFIG=${HOME_DIR}/config.working.json
elif [ -f "${HOME_DIR}/config.json" ]; then
export CONFIG=${HOME_DIR}/config.json
else
echo "NO CONFIG FILE FOUND"
fi
if [ "$1" = "crond" ]; then
if [ -f ${CONFIG} ]; then
build_crontab
else
echo "Unable to find ${CONFIG}"
fi
fi
echo "$@"
exec "$@"
}
start_app "$@"

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash
set -e
# This file is for testing the logging of docker output #8
LOG_FILE=./jobs.log
touch ${LOG_FILE}
UUID="xxxxxxxxxxxxxxxxx"