dockerfiles: initial commit of balenalib dockerfiles

Add dockerfiles for alpine and debian images, based on upstream
balenalib/arch-distro-node images.

Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
This commit is contained in:
Kyle Harding 2021-01-15 09:28:52 -05:00
parent 4cd3ef8b91
commit a9be42e280
No known key found for this signature in database
GPG Key ID: 2AD73EC1FB4865E3
5 changed files with 289 additions and 0 deletions

167
docker/DOCKER.md Normal file
View File

@ -0,0 +1,167 @@
# Docker Images for balena CLI
Docker images with balena CLI and docker-in-docker.
## Available architectures
- `rpi`
- `armv7hf`
- `aarch64` (debian only)
- `amd64`
- `i386`
## Basic Usage
Here's a small example of running a single, detached container
in the background and using `docker exec` to run balena CLI commands.
```
$ docker run --detach --privileged --network host --name cli --rm -it balenalib/amd64-debian-balenacli /bin/bash
$ docker exec -it cli balena version -a
balena-cli version "12.38.1"
Node.js version "12.19.1"
$ docker exec -it cli balena login --token abc...
$ docker exec -it cli balena whoami
== ACCOUNT INFORMATION
USERNAME: ...
EMAIL: ...
URL: balena-cloud.com
$ docker exec -it cli balena apps
ID APP NAME SLUG DEVICE TYPE ONLINE DEVICES DEVICE COUNT
1491721 test-nuc gh_paulo_castro/test-nuc intel-nuc 0 1
...
$ docker exec -it cli balena app test-nuc
== test-nuc
ID: 149...
DEVICE TYPE: intel-nuc
SLUG: gh_.../test-nuc
COMMIT: ce9...
```
## Advanced Usage
The following are examples of running the docker image in various
modes in order to allow only the required functionality, and not
elevate permissions unless required.
### scan
- <https://www.balena.io/docs/reference/balena-cli/#scan>
```bash
# balena scan requires the host network and NET_ADMIN
docker run --rm -it --cap-add NET_ADMIN --network host \
balenalib/amd64-debian-balenacli scan
```
### ssh
- <https://www.balena.io/docs/reference/balena-cli/#login>
- <https://www.balena.io/docs/reference/balena-cli/#key-add-name-path>
- <https://www.balena.io/docs/reference/balena-cli/#ssh-applicationordevice-service>
```bash
# balena ssh requires a private ssh key
docker run --rm -it -e SSH_PRIVATE_KEY="$(</path/to/priv/key)" \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena ssh f49cefd my-service
> exit
# OR use your host ssh agent socket with a key already loaded
docker run --rm -it -e SSH_AUTH_SOCK -v "$(dirname "${SSH_AUTH_SOCK}")" \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena ssh f49cefd my-service
> exit
```
### build | deploy
- <https://www.balena.io/docs/reference/balena-cli/#build-source>
- <https://www.balena.io/docs/reference/balena-cli/#deploy-appname-image>
```bash
# docker-in-docker requires SYS_ADMIN
# note that we are mounting your app source into the container
# with -v $PWD:$PWD -w $PWD for convenience
docker run --rm -it --cap-add SYS_ADMIN \
-v $PWD:$PWD -w $PWD \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena build --application myApp
> balena deploy myApp
> exit
# OR use your host docker socket
# note that we are mounting your app source into the container
# with -v $PWD:$PWD -w $PWD for convenience
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD:$PWD -w $PWD \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena build --application myApp
> balena deploy myApp
> exit
```
### preload
- <https://www.balena.io/docs/reference/balena-cli/#os-download-type>
- <https://www.balena.io/docs/reference/balena-cli/#os-configure-image>
- <https://www.balena.io/docs/reference/balena-cli/#preload-image>
```bash
# docker-in-docker requires SYS_ADMIN
docker run --rm -it --cap-add SYS_ADMIN \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena os download raspberrypi3 -o raspberry-pi.img
> balena os configure raspberry-pi.img --app MyApp
> balena preload raspberry-pi.img --app MyApp --commit current
> exit
# OR use your host docker socket
# note the .img path must be the same on the host as in the container
# therefore we are using -v $PWD:$PWD -w $PWD so the paths align
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD:$PWD -w $PWD \
balenalib/amd64-debian-balenacli /bin/bash
> balena login --credentials --email johndoe@gmail.com --password secret
> balena os download raspberrypi3 -o raspberry-pi.img
> balena os configure raspberry-pi.img --app MyApp
> balena preload raspberry-pi.img --app MyApp --commit current
> exit
```
## Custom images / contributing
The following script / steps may be used to create custom CLI images or
to contribute bug reports, fixes or features.
```bash
# optionally enable qemu for cross-compiling
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
export BALENA_ARCH="amd64"
export BALENA_DISTRO="debian"
export BALENA_CLI_VERSION="12.38.0"
docker build ${BALENA_DISTRO} \
--build-arg BALENA_ARCH \
--build-arg BALENA_CLI_VERSION \
--tag "balenalib/${BALENA_ARCH}-${BALENA_DISTRO}-balenacli:${BALENA_CLI_VERSION}" \
--tag "balenalib/${BALENA_ARCH}-${BALENA_DISTRO}-balenacli:latest" \
--pull
```

32
docker/alpine/Dockerfile Normal file
View File

@ -0,0 +1,32 @@
ARG BALENA_ARCH
FROM balenalib/${BALENA_ARCH}-alpine-node:12-run
WORKDIR /usr/src/app
ARG BALENA_CLI_VERSION
# hadolint ignore=DL3018
RUN apk add --no-cache -t .build-deps \
build-base \
curl \
git \
linux-headers \
python3 && \
npm install balena-cli@${BALENA_CLI_VERSION} -g --production --unsafe-perm && \
apk del --purge .build-deps
# fail early if balena binary won't run
RUN balena --version
# https://github.com/balena-io/balena-cli/blob/master/INSTALL-LINUX.md#additional-dependencies
# hadolint ignore=DL3018
RUN apk add --no-cache avahi bash ca-certificates docker openssh
COPY init.sh ./
RUN chmod +x ./init.sh
ENTRYPOINT [ "./init.sh" ]
CMD [ "--help" ]

28
docker/alpine/init.sh Normal file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# start dockerd if socket not mounted from host
if ! docker info >/dev/null 2>&1
then
[ -e /var/run/docker.sock ] && rm /var/run/docker.sock
dockerd &
fi
# start ssh agent if socket not mounted from host
if [ ! -e "${SSH_AUTH_SOCK}" ]
then
eval "$(ssh-agent -s)"
fi
# install private ssh key if one is provided
if [ -n "${SSH_PRIVATE_KEY}" ]
then
echo "${SSH_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
fi
# try to determine if an executable was provided or just args
if [ "${1}" = "balena" ] || [ -x "${1}" ] || "${1}" -v >/dev/null 2>&1
then
exec "$@"
else
exec balena "$@"
fi

34
docker/debian/Dockerfile Normal file
View File

@ -0,0 +1,34 @@
ARG BALENA_ARCH
FROM balenalib/${BALENA_ARCH}-debian-node:12-run
WORKDIR /usr/src/app
ARG BALENA_CLI_VERSION
ENV DEBCONF_NONINTERACTIVE_SEEN true
ENV DEBIAN_FRONTEND noninteractive
# hadolint ignore=DL3008,SC2086
RUN buildDeps="build-essential ca-certificates curl git python3" && \
apt-get update && apt-get install --no-install-recommends -y $buildDeps && \
npm install balena-cli@${BALENA_CLI_VERSION} -g --production --unsafe-perm && \
apt-get purge -y --auto-remove $buildDeps && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# fail early if balena binary won't run
RUN balena --version
# https://github.com/balena-io/balena-cli/blob/master/INSTALL-LINUX.md#additional-dependencies
# hadolint ignore=DL3008
RUN apt-get update && apt-get install --no-install-recommends -y \
avahi-daemon ca-certificates docker.io openssh-client && \
apt-get clean && rm -rf /var/lib/apt/lists/*
COPY init.sh ./
RUN chmod +x ./init.sh
ENTRYPOINT [ "./init.sh" ]
CMD [ "--help" ]

28
docker/debian/init.sh Normal file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# start dockerd if socket not mounted from host
if ! docker info >/dev/null 2>&1
then
[ -e /var/run/docker.sock ] && rm /var/run/docker.sock
dockerd &
fi
# start ssh agent if socket not mounted from host
if [ ! -e "${SSH_AUTH_SOCK}" ]
then
eval "$(ssh-agent -s)"
fi
# install private ssh key if one is provided
if [ -n "${SSH_PRIVATE_KEY}" ]
then
echo "${SSH_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
fi
# try to determine if an executable was provided or just args
if [ "${1}" = "balena" ] || [ -x "${1}" ] || "${1}" -v >/dev/null 2>&1
then
exec "$@"
else
exec balena "$@"
fi