Phase 3 — Deploy & Use · Step 9 of 14

BUILD — Build Images from a Dockerfile

When no ready-made ARM image exists on Docker Hub, you build your own from a Dockerfile. This example builds a MariaDB 10.3 image for the Raspberry Pi.

When Do You Need to Build?

Most popular images on Docker Hub have ARM variants. But sometimes you'll only find x86/amd64 builds, or the ARM image is outdated. In that case, build from source.

For this guide: MariaDB 10.3 was only available for AMD64. The Raspberry Pi runs arm32v7 / armhf, so a custom build was needed.

Starting point: github.com/docker-library/mariadb

🏗️
Stack context: Once built, tag your image with --tag yourname/imagename:tag and push it to Docker Hub. Your docker-compose.yml then references it by that tag. When docker stack deploy runs, the Swarm manager pulls the image from Docker Hub onto every worker node automatically.

Set Up a Build Directory

Create working directory
$ mkdir mariadb10.3
$ cd mariadb10.3
# Save your Dockerfile and docker-entrypoint.sh here

Build the Image

Run on MASTER — build from current directory
$ docker build --tag jorgenlarsen/mariadb10.3:rpi .
# Note the trailing "." — it means "use current directory as build context"

Example Dockerfile (MariaDB 10.3 for Debian/ARM)

Dockerfile
# vim:set ft=dockerfile:
FROM debian:latest

RUN groupadd -r mysql && useradd -r -g mysql mysql

ENV MARIADB_MAJOR 10.3
ENV MARIADB_VERSION 1:10.3.23-0+deb10u1

RUN set -ex; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
      pwgen tzdata xz-utils gnupg dirmngr ca-certificates wget; \
    rm -rf /var/lib/apt/lists/*

# gosu for privilege dropping
ENV GOSU_VERSION 1.12
RUN set -eux; \
    dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
    wget -O /usr/local/bin/gosu \
      "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
    chmod +x /usr/local/bin/gosu; \
    gosu nobody true

RUN mkdir /docker-entrypoint-initdb.d

# Add MariaDB repo
RUN set -e; \
    echo "deb http://ftp.osuosl.org/pub/mariadb/repo/$MARIADB_MAJOR/debian buster main" \
      > /etc/apt/sources.list.d/mariadb.list

RUN set -ex; \
    apt-get update; \
    apt-get install -y mariadb-server="$MARIADB_VERSION" mariadb-backup socat; \
    rm -rf /var/lib/mysql; \
    mkdir -p /var/lib/mysql /var/run/mysqld; \
    chown -R mysql:mysql /var/lib/mysql /var/run/mysqld; \
    chmod 777 /var/run/mysqld; \
    echo '[mysqld]\nskip-host-cache\nskip-name-resolve' \
      > /etc/mysql/conf.d/docker.cnf

VOLUME /var/lib/mysql
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]

Verify the Build

List images to confirm the build succeeded
$ docker images

REPOSITORY                 TAG      IMAGE ID       CREATED        SIZE
jorgenlarsen/mariadb10.3   rpi      09f38af10d8f   2 weeks ago    316 MB
portainer/portainer-ce     latest   5526251cc61f   7 weeks ago    163 MB
⚠️
Building images on a Raspberry Pi is slow. A complex image can take 30–60 minutes. Plan accordingly and don't abort partway through.
📘
Official reference: docs.docker.com — docker build