From 8da26a4e65ebfc536cb1b4f855935094650fd561 Mon Sep 17 00:00:00 2001 From: Cameron Wood Date: Thu, 31 Dec 2020 10:37:59 +0100 Subject: [PATCH] Initial commit --- .github/workflows/main.yml | 36 +++++++++++++++ Dockerfile-alpine | 55 +++++++++++++++++++++++ Dockerfile-debian | 50 +++++++++++++++++++++ Dockerfile-ubuntu | 50 +++++++++++++++++++++ LICENSE | 21 +++++++++ Makefile | 90 ++++++++++++++++++++++++++++++++++++++ README.md | 75 +++++++++++++++++++++++++++++++ crontab | 1 + 8 files changed, 378 insertions(+) create mode 100644 .github/workflows/main.yml create mode 100644 Dockerfile-alpine create mode 100644 Dockerfile-debian create mode 100644 Dockerfile-ubuntu create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 crontab diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..403aa4c --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +name: main + +on: + push: + branches: + - "*" # run for branches + tags: + - "*" # run for tags + +jobs: + main: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v1 + + # Set up Qemu for Buildx + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + # Set up Buildx for Docker + - name: Set up Buildx for Docker + uses: docker/setup-buildx-action@v1 + + # Login to Docker Hub + - name: Login to Docker Hub + if: startsWith(github.ref, 'refs/tags/') + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # Build images + - name: Build images + run: make ci diff --git a/Dockerfile-alpine b/Dockerfile-alpine new file mode 100644 index 0000000..23e5334 --- /dev/null +++ b/Dockerfile-alpine @@ -0,0 +1,55 @@ +FROM --platform=$TARGETPLATFORM alpine:3.12 + +ARG TARGETARCH +ARG TARGETPLATFORM +ARG TARGETVARIANT + +ENV ISYNC_VERSION="1.3.1-r1" \ + CURL_VERSION="7.69.1-r3" \ + CA_CERTIFICATES_VERSION="20191127-r4" \ + PROCPS_VERSION="3.3.16-r0" \ + BASH_VERSION="5.0.17-r0" + +SHELL ["/bin/sh", "-o", "pipefail", "-c"] + +RUN apk add --no-cache \ + isync="${ISYNC_VERSION}" \ + ca-certificates="${CA_CERTIFICATES_VERSION}" \ + curl="${CURL_VERSION}" \ + procps="${PROCPS_VERSION}" \ + bash="${BASH_VERSION}" \ + && addgroup mbsync \ + && adduser mbsync -G mbsync -D -h /workdir + +ENV SUPERCRONIC_VERSION=v0.1.12 +ENV SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC="supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM="SUPERCRONIC_SHA1SUM_${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM_amd64="048b95b48b708983effb2e5c935a1ef8483d9e3e" \ + SUPERCRONIC_SHA1SUM_arm64="8baba3dd0b0b13552aca179f6ef10d55e5dee28b" \ + SUPERCRONIC_SHA1SUM_arm="d72d3d40065c0188b3f1a0e38fe6fecaa098aad5" + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN curl -fsSLO "${SUPERCRONIC_URL}" \ + && echo "${!SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ + && chmod +x "${SUPERCRONIC}" \ + && mv "${SUPERCRONIC}" "/usr/local/bin/${SUPERCRONIC}" \ + && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic + +COPY crontab /etc/crontab + +USER mbsync + +CMD /usr/local/bin/supercronic /etc/crontab + +ARG CREATED +ARG REVISION=HEAD + +LABEL org.opencontainers.image.authors="https://github.com/cewood" \ + org.opencontainers.image.created="${CREATED}" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.revision="${REVISION}" \ + org.opencontainers.image.source="https://github.com/cewood/mbsync-docker/tree/${REVISION}" \ + org.opencontainers.image.title="cewood/mbsync" \ + org.opencontainers.image.url="https://github.com/cewood/mbsync-docker" diff --git a/Dockerfile-debian b/Dockerfile-debian new file mode 100644 index 0000000..c95a582 --- /dev/null +++ b/Dockerfile-debian @@ -0,0 +1,50 @@ +FROM --platform=$TARGETPLATFORM debian:10.7-slim + +ARG TARGETARCH +ARG TARGETPLATFORM +ARG TARGETVARIANT + +ENV ISYNC_VERSION="1.3.0-2" \ + CURL_VERSION="7.64.0-4+deb10u1" \ + CA_CERTIFICATES_VERSION="20190110" \ + PROCPS_VERSION="2:3.3.15-2" + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update \ + && apt-get --no-install-recommends --yes install \ + isync="${ISYNC_VERSION}" \ + ca-certificates="${CA_CERTIFICATES_VERSION}" \ + curl="${CURL_VERSION}" \ + procps="${PROCPS_VERSION}" \ + && useradd --home-dir /workdir mbsync \ + && rm -rf /var/cache/apt + +ENV SUPERCRONIC_VERSION=v0.1.12 +ENV SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC="supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM="SUPERCRONIC_SHA1SUM_${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM_amd64="048b95b48b708983effb2e5c935a1ef8483d9e3e" \ + SUPERCRONIC_SHA1SUM_arm64="8baba3dd0b0b13552aca179f6ef10d55e5dee28b" \ + SUPERCRONIC_SHA1SUM_arm="d72d3d40065c0188b3f1a0e38fe6fecaa098aad5" + +RUN curl -kfsSLO "${SUPERCRONIC_URL}" \ + && echo "${!SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ + && chmod +x "${SUPERCRONIC}" \ + && mv "${SUPERCRONIC}" "/usr/local/bin/${SUPERCRONIC}" \ + && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic + +COPY crontab /etc/crontab + +USER mbsync + +ARG CREATED +ARG REVISION=HEAD + +LABEL org.opencontainers.image.authors="https://github.com/cewood" \ + org.opencontainers.image.created="${CREATED}" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.revision="${REVISION}" \ + org.opencontainers.image.source="https://github.com/cewood/mbsync-docker/tree/${REVISION}" \ + org.opencontainers.image.title="cewood/mbsync" \ + org.opencontainers.image.url="https://github.com/cewood/mbsync-docker" diff --git a/Dockerfile-ubuntu b/Dockerfile-ubuntu new file mode 100644 index 0000000..81a2b88 --- /dev/null +++ b/Dockerfile-ubuntu @@ -0,0 +1,50 @@ +FROM --platform=$TARGETPLATFORM ubuntu:20.04 + +ARG TARGETARCH +ARG TARGETPLATFORM +ARG TARGETVARIANT + +ENV ISYNC_VERSION="1.3.0-2" \ + CURL_VERSION="7.68.0-1ubuntu2.4" \ + CA_CERTIFICATES_VERSION="20201027ubuntu0.20.04.1" \ + PROCPS_VERSION="2:3.3.16-1ubuntu2" + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN apt-get update \ + && apt-get --no-install-recommends --yes install \ + isync="${ISYNC_VERSION}" \ + ca-certificates="${CA_CERTIFICATES_VERSION}" \ + curl="${CURL_VERSION}" \ + procps="${PROCPS_VERSION}" \ + && useradd --home-dir /workdir mbsync \ + && rm -rf /var/cache/apt + +ENV SUPERCRONIC_VERSION=v0.1.12 +ENV SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC="supercronic-linux-${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM="SUPERCRONIC_SHA1SUM_${TARGETARCH}" \ + SUPERCRONIC_SHA1SUM_amd64="048b95b48b708983effb2e5c935a1ef8483d9e3e" \ + SUPERCRONIC_SHA1SUM_arm64="8baba3dd0b0b13552aca179f6ef10d55e5dee28b" \ + SUPERCRONIC_SHA1SUM_arm="d72d3d40065c0188b3f1a0e38fe6fecaa098aad5" + +RUN curl -fsSLO "${SUPERCRONIC_URL}" \ + && echo "${!SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ + && chmod +x "${SUPERCRONIC}" \ + && mv "${SUPERCRONIC}" "/usr/local/bin/${SUPERCRONIC}" \ + && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic + +COPY crontab /etc/crontab + +USER mbsync + +ARG CREATED +ARG REVISION=HEAD + +LABEL org.opencontainers.image.authors="https://github.com/cewood" \ + org.opencontainers.image.created="${CREATED}" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.revision="${REVISION}" \ + org.opencontainers.image.source="https://github.com/cewood/mbsync-docker/tree/${REVISION}" \ + org.opencontainers.image.title="cewood/mbsync" \ + org.opencontainers.image.url="https://github.com/cewood/mbsync-docker" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba5197e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Cameron Wood + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..67ee5aa --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +ARCH = $(or $(shell printenv ARCH),$(shell echo linux/amd64,linux/arm64,linux/arm/v7)) +BUILD_FLAGS = $(or $(shell printenv BUILD_FLAGS),--pull) +CREATED = $(or $(shell printenv CREATED),$(shell date --rfc-3339=seconds)) +DISTS = $(or $(shell printenv DISTS),alpine debian ubuntu) +DOCKER_INTERACTIVE = $(if $(shell printenv GITHUB_ACTIONS),-t,-it) +GIT_REVISION = $(or $(shell printenv GIT_REVISION), $(shell git describe --match= --always --abbrev=7 --dirty)) +IMAGE = $(or $(shell printenv IMAGE),cewood/mbsync) +IMAGE_TAG = $(or $(shell printenv IMAGE_TAG),${DIST}_${TAG_REVISION}) +TAG_REVISION = $(or $(shell printenv TAG_REVISION),${GIT_REVISION}) + + +.PHONY: dists +dists: $(patsubst %,build-%,${DISTS}) + +.PHONY: alpine +alpine: build-alpine load-alpine dive-alpine + $(MAKE) build-alpine TAG_REVISION=latest + $(MAKE) load-alpine TAG_REVISION=latest + +.PHONY: debian +debian: build-debian load-debian dive-debian + $(MAKE) build-debian TAG_REVISION=latest + $(MAKE) load-debian TAG_REVISION=latest + +.PHONY: ubuntu +ubuntu: build-ubuntu load-ubuntu dive-ubuntu + $(MAKE) build-ubuntu TAG_REVISION=latest + $(MAKE) load-ubuntu TAG_REVISION=latest + +.PHONY: build-% +build-%: + $(MAKE) build DIST=$* + +.PHONY: build +build: + DOCKER_CLI_EXPERIMENTAL=enabled \ + docker \ + buildx build \ + ${BUILD_FLAGS} \ + --build-arg CREATED="${CREATED}" \ + --build-arg REVISION="${GIT_REVISION}" \ + --platform ${ARCH} \ + --tag ${IMAGE}:${IMAGE_TAG} \ + -f Dockerfile-${DIST} \ + . + +.PHONY: load-% +load-%: + $(MAKE) load DIST=$* + +.PHONY: load +load: + $(MAKE) build DIST=${DIST} BUILD_FLAGS=--load ARCH=linux/amd64 + +.PHONY: inspect +inspect: + docker inspect ${IMAGE}:${IMAGE_TAG} + +.PHONY: binfmt-setup +binfmt-setup: + docker \ + run \ + --rm \ + --privileged \ + docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d + +.PHONY: buildx-setup +buildx-setup: + DOCKER_CLI_EXPERIMENTAL=enabled \ + docker \ + buildx \ + create \ + --use \ + --name multiarch + +.PHONY: dive-% +dive-%: + $(MAKE) dive DIST=$* + +.PHONY: dive +dive: + docker run --rm -it \ + -e CI=true \ + -v /var/run/docker.sock:/var/run/docker.sock \ + wagoodman/dive:v0.9.2 ${IMAGE}:${IMAGE_TAG} + +.PHONY: ci +ci: + $(MAKE) dists BUILD_FLAGS=$(if $(findstring tags,${GITHUB_REF}),--push,--pull) + $(MAKE) dists BUILD_FLAGS=$(if $(findstring tags,${GITHUB_REF}),--push,--pull) TAG_REVISION=latest diff --git a/README.md b/README.md new file mode 100644 index 0000000..e367c13 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Mbsync Docker + +An opinionated set of simple Docker containers with Mbsync ([Isync](https://isync.sourceforge.io/)) and [Supercronic](https://github.com/aptible/supercronic). + + +## Usage + +Being slightly opinionated there isn't any `ENTRYPOINT` specified, instead only a default `CMD` to run Supercronic with the bundled `/etc/crontab` file that simply echoes a short message once a minute. This means you can easily change what the container does without having to override an `ENTRYPOINT`, and if you want to use the Supercronic functionality you only need to mount in your own crontab file at `/etc/crontab` and run the container without any additional args. + + +### Docker Run + +``` +$ docker run --rm -it \ + -v $PWD/mbsyncrc:/workdir/.mbsyncrc \ + -v $PWD:/workdir/data \ + -w /workdir \ + cewood/mbsync:alpine_UPDATEME \ + mbsync --all --pull --create-slave --expunge-slave --verbose +``` + + +### Docker Compose + +``` +version: "3.4" +services: + mbsync: + image: cewood/mbsync:alpine_UPDATEME + container_name: mbsync + working_dir: /workdir + volumes: + - "/mnt/storage/containers/mbsync/data:/workdir/data" + - "./mbsync/mbsyncrc:/workdir/.mbsyncrc" + - "./mbsync/crontab:/etc/crontab" # Be sure to update the crontab with your command(s) + restart: unless-stopped + labels: + org.label-schema.group: "backups" +``` + + +## Image variants + +Currently the following distributions are included: + + - Alpine 3.12 + - Debian 10.7 (Slim variant) + - Ubuntu 20.04 (LTS release) + + +## Supported architectures + +Currently the following architectures are built for each image variant: + + - linux/amd64 + - linux/arm64 + - linux/arm/v7 + + +# Frequently Asked Questions +## Why another Mbsync Docker Image + +There was already a number of Mbsync/Isync images available on the Docker Hub, but unfortunately they all had their various short comings. Most weren't built via a Continuous Integration tool, none had any image tags, and none provided the Dockerfile or a link to their SCM tool of choice to inspect the image contents and build. Thus I decided to make my own set of images for Mbsync to address all these points, and here we are. + + +## Why isn't the image named Isync + +Great question! Since most people use Isync via the Mbsync command, I decided to name the image Mbsync, as this appears to be what most people search for and are familiar with. And the project itself states: + +> While isync is the project name, mbsync is the current executable name; this change was necessary because of massive changes in the user interface. An isync executable still exists; it is a compatibility wrapper around mbsync. + + +## Why Supercronic and not just regular cron + +If we were running a normal system in an interactive manner, then normal Cron or friends (Anacron, Fcron, etc) would be fine choices. However in a containerised environment, these traditional cron implementations have some downsides, that make Supercronic a better fit. Namely the printing of jobs output to stdout, hence when running Supercronic as the ENTRYPOINT/CMD I can see the output of the jobs being run without having to jump through any hoops. There are undoubtedly other features that Supercronic brings with it that make it a better fit for use in containers, but this was the main motivator for me. diff --git a/crontab b/crontab new file mode 100644 index 0000000..9f03a3c --- /dev/null +++ b/crontab @@ -0,0 +1 @@ +* * * * * echo "Hello from Supercronic"