serve/docker: build docker plugin for multiple platforms #5668

Fixes #5462

Co-authored-by: Ivan Andreev <ivandeex@gmail.com>
This commit is contained in:
Thomas Stachl 2021-07-15 15:35:54 -07:00 committed by Ivan Andreev
parent 4b1ada2d51
commit 015b250905
8 changed files with 95 additions and 93 deletions

View File

@ -37,35 +37,23 @@ jobs:
if: github.repository == 'rclone/rclone' if: github.repository == 'rclone/rclone'
needs: build needs: build
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Build and publish docker volume plugin name: Build docker plugin job
steps: steps:
- name: Checkout master - name: Checkout master
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set plugin parameters - name: Build and publish docker plugin
shell: bash shell: bash
run: | run: |
GITHUB_REF=${{ github.ref }} VER=${GITHUB_REF#refs/tags/}
PLUGIN_USER=rclone
PLUGIN_IMAGE_USER=rclone docker login --username ${{ secrets.DOCKER_HUB_USER }} \
PLUGIN_IMAGE_NAME=docker-volume-rclone --password-stdin <<< "${{ secrets.DOCKER_HUB_PASSWORD }}"
PLUGIN_IMAGE_TAG=${GITHUB_REF#refs/tags/} for PLUGIN_ARCH in amd64 arm64 arm/v7 ;do
PLUGIN_IMAGE=${PLUGIN_IMAGE_USER}/${PLUGIN_IMAGE_NAME}:${PLUGIN_IMAGE_TAG} export PLUGIN_USER PLUGIN_ARCH
PLUGIN_IMAGE_LATEST=${PLUGIN_IMAGE_USER}/${PLUGIN_IMAGE_NAME}:latest make docker-plugin PLUGIN_TAG=${PLUGIN_ARCH/\//-}
make docker-plugin PLUGIN_TAG=${PLUGIN_ARCH/\//-}-${VER#v}
echo "PLUGIN_IMAGE_USER=${PLUGIN_IMAGE_USER}" >> $GITHUB_ENV done
echo "PLUGIN_IMAGE_NAME=${PLUGIN_IMAGE_NAME}" >> $GITHUB_ENV make docker-plugin PLUGIN_ARCH=amd64 PLUGIN_TAG=latest
echo "PLUGIN_IMAGE_TAG=${PLUGIN_IMAGE_TAG}" >> $GITHUB_ENV make docker-plugin PLUGIN_ARCH=amd64 PLUGIN_TAG=${VER#v}
echo "PLUGIN_IMAGE=${PLUGIN_IMAGE}" >> $GITHUB_ENV
echo "PLUGIN_IMAGE_LATEST=${PLUGIN_IMAGE_LATEST}" >> $GITHUB_ENV
- name: Build image
shell: bash
run: |
make docker-plugin
- name: Push image
shell: bash
run: |
docker login -u ${{ secrets.DOCKER_HUB_USER }} -p ${{ secrets.DOCKER_HUB_PASSWORD }}
make docker-plugin-push PLUGIN_IMAGE=${PLUGIN_IMAGE}
make docker-plugin-push PLUGIN_IMAGE=${PLUGIN_IMAGE_LATEST}

View File

@ -258,34 +258,31 @@ winzip:
zip -9 rclone-$(TAG).zip rclone.exe zip -9 rclone-$(TAG).zip rclone.exe
# docker volume plugin # docker volume plugin
PLUGIN_IMAGE_USER ?= rclone PLUGIN_USER ?= rclone
PLUGIN_IMAGE_TAG ?= latest PLUGIN_TAG ?= latest
PLUGIN_IMAGE_NAME ?= docker-volume-rclone PLUGIN_BASE_TAG ?= latest
PLUGIN_IMAGE ?= $(PLUGIN_IMAGE_USER)/$(PLUGIN_IMAGE_NAME):$(PLUGIN_IMAGE_TAG) PLUGIN_ARCH ?= amd64
PLUGIN_IMAGE := $(PLUGIN_USER)/docker-volume-rclone:$(PLUGIN_TAG)
PLUGIN_BASE_IMAGE := rclone/rclone:latest PLUGIN_BASE := $(PLUGIN_USER)/rclone:$(PLUGIN_BASE_TAG)
PLUGIN_BUILD_DIR := ./build/docker-plugin PLUGIN_BUILD_DIR := ./build/docker-plugin
PLUGIN_CONTRIB_DIR := ./cmd/serve/docker/contrib/plugin PLUGIN_CONTRIB_DIR := ./contrib/docker-plugin/managed
PLUGIN_CONFIG := $(PLUGIN_CONTRIB_DIR)/config.json
PLUGIN_DOCKERFILE := $(PLUGIN_CONTRIB_DIR)/Dockerfile
PLUGIN_CONTAINER := docker-volume-rclone-dev-$(shell date +'%Y%m%d-%H%M%S')
docker-plugin: docker-plugin-rootfs docker-plugin-create
docker-plugin-image: rclone
docker build --no-cache --pull --build-arg BASE_IMAGE=${PLUGIN_BASE_IMAGE} -t ${PLUGIN_IMAGE} -f ${PLUGIN_DOCKERFILE} .
docker-plugin-rootfs: docker-plugin-image
mkdir -p ${PLUGIN_BUILD_DIR}/rootfs
docker create --name ${PLUGIN_CONTAINER} ${PLUGIN_IMAGE}
docker export ${PLUGIN_CONTAINER} | tar -x -C ${PLUGIN_BUILD_DIR}/rootfs
docker rm -vf ${PLUGIN_CONTAINER}
cp ${PLUGIN_CONFIG} ${PLUGIN_BUILD_DIR}/config.json
docker-plugin-create: docker-plugin-create:
docker plugin rm -f ${PLUGIN_IMAGE} 2>/dev/null || true docker buildx inspect |grep -q /${PLUGIN_ARCH} || \
docker run --rm --privileged tonistiigi/binfmt --install all
rm -rf ${PLUGIN_BUILD_DIR}
docker buildx build \
--no-cache --pull \
--build-arg BASE_IMAGE=${PLUGIN_BASE} \
--platform linux/${PLUGIN_ARCH} \
--output ${PLUGIN_BUILD_DIR}/rootfs \
${PLUGIN_CONTRIB_DIR}
cp ${PLUGIN_CONTRIB_DIR}/config.json ${PLUGIN_BUILD_DIR}
docker plugin rm --force ${PLUGIN_IMAGE} 2>/dev/null || true
docker plugin create ${PLUGIN_IMAGE} ${PLUGIN_BUILD_DIR} docker plugin create ${PLUGIN_IMAGE} ${PLUGIN_BUILD_DIR}
docker-plugin-push: docker-plugin-create docker-plugin-push:
docker plugin push ${PLUGIN_IMAGE} docker plugin push ${PLUGIN_IMAGE}
docker plugin rm ${PLUGIN_IMAGE} docker plugin rm ${PLUGIN_IMAGE}
docker-plugin: docker-plugin-create docker-plugin-push

View File

@ -1,35 +0,0 @@
ARG BASE_IMAGE=rclone/rclone:latest
ARG BUILD_PLATFORM=linux/amd64
ARG TARGET_PLATFORM=linux/amd64
# temporary build image
FROM --platform=${BUILD_PLATFORM} golang:alpine AS BUILD_ENV
COPY . /src
WORKDIR /src
RUN apk add --no-cache make git bash && \
CGO_ENABLED=0 \
GOARCH=$(echo ${TARGET_PLATFORM} | cut -d '/' -f2) \
make rclone
# plugin image
FROM ${BASE_IMAGE}
COPY --from=BUILD_ENV /src/rclone /usr/local/bin/rclone
RUN mkdir -p /data/config /data/cache /mnt \
&& /usr/local/bin/rclone version
ENV RCLONE_CONFIG=/data/config/rclone.conf
ENV RCLONE_CACHE_DIR=/data/cache
ENV RCLONE_BASE_DIR=/mnt
ENV RCLONE_VERBOSE=0
ENV HTTP_PROXY=
ENV HTTPS_PROXY=
ENV NO_PROXY=
WORKDIR /data
ENTRYPOINT ["/usr/local/bin/rclone"]
CMD ["serve", "docker"]

View File

@ -0,0 +1,25 @@
ARG BASE_IMAGE=rclone/rclone:latest
FROM ${BASE_IMAGE} as binaries
# build plugin image
FROM alpine:latest
# put rclone in /usr/bin, reserve /usr/local/bin for plugin wrappers
COPY --from=binaries /usr/local/bin/rclone /usr/bin/rclone
RUN mkdir -p /data/config /data/cache /mnt \
&& apk --no-cache add ca-certificates fuse tzdata \
&& echo "user_allow_other" >> /etc/fuse.conf \
&& rclone version
ENV RCLONE_CONFIG=/data/config/rclone.conf
ENV RCLONE_CACHE_DIR=/data/cache
ENV RCLONE_BASE_DIR=/mnt
ENV RCLONE_VERBOSE=0
ENV HTTP_PROXY=
ENV HTTPS_PROXY=
ENV NO_PROXY=
WORKDIR /data
ENTRYPOINT ["rclone", "serve", "docker"]

View File

@ -1,6 +1,6 @@
{ {
"description": "Rclone volume plugin for Docker", "description": "Rclone volume plugin for Docker",
"documentation": "https://rclone.org/", "documentation": "https://rclone.org/docker",
"interface": { "interface": {
"socket": "rclone.sock", "socket": "rclone.sock",
"types": ["docker.volumedriver/1.0"] "types": ["docker.volumedriver/1.0"]
@ -18,7 +18,7 @@
"network": { "network": {
"type": "host" "type": "host"
}, },
"entrypoint": ["/usr/local/bin/rclone", "serve", "docker"], "entrypoint": ["rclone", "serve", "docker"],
"workdir": "/data", "workdir": "/data",
"args": { "args": {
"name": "args", "name": "args",

View File

@ -53,9 +53,9 @@ sudo mkdir -p /var/lib/docker-plugins/rclone/config
sudo mkdir -p /var/lib/docker-plugins/rclone/cache sudo mkdir -p /var/lib/docker-plugins/rclone/cache
``` ```
Install the managed rclone docker plugin: Install the managed rclone docker plugin for your architecture (here `amd64`):
``` ```
docker plugin install rclone/docker-volume-rclone args="-v" --alias rclone --grant-all-permissions docker plugin install rclone/docker-volume-rclone:amd64 args="-v" --alias rclone --grant-all-permissions
docker plugin list docker plugin list
``` ```
@ -321,9 +321,36 @@ By default they must exist on host at the following locations
You can [install managed plugin](https://docs.docker.com/engine/reference/commandline/plugin_install/) You can [install managed plugin](https://docs.docker.com/engine/reference/commandline/plugin_install/)
with default settings as follows: with default settings as follows:
``` ```
docker plugin install rclone/docker-volume-rclone:latest --grant-all-permissions --alias rclone docker plugin install rclone/docker-volume-rclone:amd64 --grant-all-permissions --alias rclone
``` ```
The `:amd64` part of the image specification after colon is called a _tag_.
Usually you will want to install the latest plugin for your architecture. In
this case the tag will just name it, like `amd64` above. The following plugin
architectures are currently available:
- `amd64`
- `arm64`
- `arm-v7`
Sometimes you might want a concrete plugin version, not the latest one.
Then you should use image tag in the form `:ARCHITECTURE-VERSION`.
For example, to install plugin version `v1.56.2` on architecture `arm64`
you will use tag `arm64-1.56.2` (note the removed `v`) so the full image
specification becomes `rclone/docker-volume-rclone:arm64-1.56.2`.
We also provide the `latest` plugin tag, but since docker does not support
multi-architecture plugins as of the time of this writing, this tag is
currently an **alias for `amd64`**.
By convention the `latest` tag is the default one and can be omitted, thus
both `rclone/docker-volume-rclone:latest` and just `rclone/docker-volume-rclone`
will refer to the latest plugin release for the `amd64` platform.
Also the `amd64` part can be omitted from the versioned rclone plugin tags.
For example, rclone image reference `rclone/docker-volume-rclone:amd64-1.56.2`
can be abbreviated as `rclone/docker-volume-rclone:1.56.2` for convenience.
However, for non-intel architectures you still have to use the full tag as
`amd64` or `latest` will fail to start.
Managed plugin is in fact a special container running in a namespace separate Managed plugin is in fact a special container running in a namespace separate
from normal docker containers. Inside it runs the `rclone serve docker` from normal docker containers. Inside it runs the `rclone serve docker`
command. The config and cache directories are bind-mounted into the command. The config and cache directories are bind-mounted into the
@ -395,7 +422,7 @@ actual level assigned by rclone in the encapsulated message string.
You can set custom plugin options right when you install it, _in one go_: You can set custom plugin options right when you install it, _in one go_:
``` ```
docker plugin remove rclone docker plugin remove rclone
docker plugin install rclone/docker-volume-rclone:latest \ docker plugin install rclone/docker-volume-rclone:amd64 \
--alias rclone --grant-all-permissions \ --alias rclone --grant-all-permissions \
args="-v --allow-other" config=/etc/rclone args="-v --allow-other" config=/etc/rclone
docker plugin inspect rclone docker plugin inspect rclone
@ -434,8 +461,8 @@ sudo apt-get -y install fuse
``` ```
Download two systemd configuration files: Download two systemd configuration files:
[docker-volume-rclone.service](https://raw.githubusercontent.com/rclone/rclone/master/cmd/serve/docker/contrib/systemd/docker-volume-rclone.service) [docker-volume-rclone.service](https://raw.githubusercontent.com/rclone/rclone/master/contrib/docker-plugin/systemd/docker-volume-rclone.service)
and [docker-volume-rclone.socket](https://raw.githubusercontent.com/rclone/rclone/master/cmd/serve/docker/contrib/systemd/docker-volume-rclone.socket). and [docker-volume-rclone.socket](https://raw.githubusercontent.com/rclone/rclone/master/contrib/docker-plugin/systemd/docker-volume-rclone.socket).
Put them to the `/etc/systemd/system/` directory: Put them to the `/etc/systemd/system/` directory:
``` ```
@ -489,7 +516,7 @@ Use `journalctl --unit docker` to see managed plugin output as part of
the docker daemon log. Note that docker reflects plugin lines as _errors_ the docker daemon log. Note that docker reflects plugin lines as _errors_
but their actual level can be seen from encapsulated message string. but their actual level can be seen from encapsulated message string.
You will usually install the latest version of managed plugin. You will usually install the latest version of managed plugin for your platform.
Use the following commands to print the actual installed version: Use the following commands to print the actual installed version:
``` ```
PLUGID=$(docker plugin list --no-trunc | awk '/rclone/{print$1}') PLUGID=$(docker plugin list --no-trunc | awk '/rclone/{print$1}')