In the repository of the official list of versions in githab:

there are no versions for armhf. Well, I haven't found them.

Therefore, to install docker-compose on a Raspberry Pi with armhf architecture, you have the option of installing it via pip using python.

This requires the first installation of libffi-dev and libssl-dev:

sudo apt-get install libffi-dev libssl-dev

Next install python3 and pip from python3 (if you want you can also install python3-dev):

sudo apt-get install python3 python3-pip

In my case, versions 3.8.5 of python and 20.0.2 of pip are installed:

operatorvm@vmrp01ubuntu2004web:~$ python3 --version
Python 3.8.5
operatorvm@vmrp01ubuntu2004web:~$ pip3 --version
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)

Then we have to uninstall the python-configparser package to avoid problems with the 'docker python client', with:

sudo apt-get remove python-configparser

And with this we can install docker-compose using the pip3 manager with:

sudo pip3 -v install docker-compose

Putting the -v option will generate a lot of output, without fear. When finished we check the version of docker-compose:

operatorvm@vmrp01ubuntu2004web:~$ docker-compose --version
docker-compose version 1.29.2, build unknown

And to certify the installation we do what the page details

The content of the 'composetest' directory:

operatorvm@vmrp01ubuntu2004web:~/composetest$ pwd
operatorvm@vmrp01ubuntu2004web:~/composetest$ ls -la
total 24
drwxrwxr-x 2 operatorvm operatorvm 4096 Jun 18 19:20 .
drwxr-xr-x 5 operatorvm operatorvm 4096 Jun 18 19:20 ..
-rw-rw-r-- 1 operatorvm operatorvm  561 Jun 18 19:20 Dockerfile
-rw-rw-r-- 1 operatorvm operatorvm  514 Jun 18 19:18
-rw-rw-r-- 1 operatorvm operatorvm  111 Jun 18 19:20 docker-compose.yml
-rw-rw-r-- 1 operatorvm operatorvm   12 Jun 18 19:19 requirements.txt

To execute it we launch 'docker-compose up' in the 'composetest' directory where the docker-compose.yml file is located:

operatorvm@vmrp01ubuntu2004web:~/composetest$ docker-compose up
Creating network "composetest_default" with the default driver
Building web
Sending build context to Docker daemon  6.144kB
Step 1/20 : FROM python:3.7-alpine
3.7-alpine: Pulling from library/python
e160e00eb35d: Pull complete
b418005250a5: Pull complete
ccf5e58bf673: Pull complete
6de0a09ff535: Pull complete
dabe521467cf: Pull complete
Digest: sha256:deaefc5e07ef1f3420411dd5225b2fc2ab23ae7731e8cb216d9fe74557d81db5
Status: Downloaded newer image for python:3.7-alpine
 ---> 6c256ee2d829
Step 2/20 : WORKDIR /code
 ---> Running in 9fe34a0d694a
Removing intermediate container 9fe34a0d694a
 ---> 23f153d55538
Step 3/20 : ENV
 ---> Running in 59a595a2e9e1
Removing intermediate container 59a595a2e9e1
 ---> 9efc2e8caf0f
 ---> Running in 68fa8bfb25d1
Removing intermediate container 68fa8bfb25d1
 ---> 3f4ae136fe5b
Step 5/20 : RUN apk add --no-cache gcc musl-dev linux-headers
 ---> Running in 30aa82263c81
(1/12) Installing libstdc++ (10.2.1_pre1-r3)
(2/12) Installing binutils (2.35.2-r1)
(3/12) Installing libgomp (10.2.1_pre1-r3)
(4/12) Installing libatomic (10.2.1_pre1-r3)
(5/12) Installing libgphobos (10.2.1_pre1-r3)
(6/12) Installing gmp (6.2.1-r0)
(7/12) Installing isl22 (0.22-r0)
(8/12) Installing mpfr4 (4.1.0-r0)
(9/12) Installing mpc1 (1.2.0-r0)
(10/12) Installing gcc (10.2.1_pre1-r3)
(11/12) Installing linux-headers (5.7.8-r0)
(12/12) Installing musl-dev (1.2.2-r1)
Executing busybox-1.32.1-r6.trigger
OK: 89 MiB in 48 packages
Removing intermediate container 30aa82263c81
 ---> 6ec909b2874f
Step 6/20 : COPY requirements.txt requirements.txt
 ---> bd6a5d620949
Step 7/20 : RUN pip install -r requirements.txt
 ---> Running in d7b46c830158
Collecting flask
  Downloading Flask-2.0.1-py3-none-any.whl (94 kB)
Collecting redis
  Downloading redis-3.5.3-py2.py3-none-any.whl (72 kB)
Collecting Jinja2>=3.0
  Downloading Jinja2-3.0.1-py3-none-any.whl (133 kB)
Collecting itsdangerous>=2.0
  Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Collecting Werkzeug>=2.0
  Downloading Werkzeug-2.0.1-py3-none-any.whl (288 kB)
Collecting click>=7.1.2
  Downloading click-8.0.1-py3-none-any.whl (97 kB)
Collecting importlib-metadata
  Downloading importlib_metadata-4.5.0-py3-none-any.whl (17 kB)
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.0.1.tar.gz (18 kB)
Collecting typing-extensions>=3.6.4
  Downloading typing_extensions- (26 kB)
Collecting zipp>=0.5
  Downloading zipp-3.4.1-py3-none-any.whl (5.2 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe ( started
  Building wheel for MarkupSafe ( finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-2.0.1-cp37-cp37m-linux_armv7l.whl size=13920 sha256=0dc883afe22e99818b21546e658a83bc037440af5e351151d456af9577673df7
  Stored in directory: /root/.cache/pip/wheels/1a/18/04/e3b5bd888f000c2716bccc94a565239f9defc47ef93d9e7bea
Successfully built MarkupSafe
Installing collected packages: zipp, typing-extensions, MarkupSafe, importlib-metadata, Werkzeug, Jinja2, itsdangerous, click, redis, flask
Successfully installed Jinja2-3.0.1 MarkupSafe-2.0.1 Werkzeug-2.0.1 click-8.0.1 flask-2.0.1 importlib-metadata-4.5.0 itsdangerous-2.0.1 redis-3.5.3 typing-extensions- zipp-3.4.1
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv:
Removing intermediate container d7b46c830158
 ---> b66de42b40a0
Step 8/20 : EXPOSE 5000
 ---> Running in 727448409b74
Removing intermediate container 727448409b74
 ---> d8fb0c186b25
Step 9/20 : COPY . .
 ---> 7d0889b47995
Step 10/20 : CMD ["flask", "run"]# syntax=docker/dockerfile:1
 ---> Running in f6ac3d9f0462
Removing intermediate container f6ac3d9f0462
 ---> 041a75134d33
Step 11/20 : FROM python:3.7-alpine
 ---> 6c256ee2d829
Step 12/20 : WORKDIR /code
 ---> Using cache
 ---> 23f153d55538
Step 13/20 : ENV
 ---> Using cache
 ---> 9efc2e8caf0f
Step 14/20 : ENV FLASK_RUN_HOST=
 ---> Using cache
 ---> 3f4ae136fe5b
Step 15/20 : RUN apk add --no-cache gcc musl-dev linux-headers
 ---> Using cache
 ---> 6ec909b2874f
Step 16/20 : COPY requirements.txt requirements.txt
 ---> Using cache
 ---> bd6a5d620949
Step 17/20 : RUN pip install -r requirements.txt
 ---> Using cache
 ---> b66de42b40a0
Step 18/20 : EXPOSE 5000
 ---> Using cache
 ---> d8fb0c186b25
Step 19/20 : COPY . .
 ---> Using cache
 ---> 7d0889b47995
Step 20/20 : CMD ["flask", "run"]
 ---> Using cache
 ---> 041a75134d33
Successfully built 041a75134d33
Successfully tagged composetest_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
e160e00eb35d: Already exists
102bb19e3a85: Pull complete
e0a40a4b302d: Pull complete
760a1d1d4e78: Pull complete
1e56acfeece4: Pull complete
0a9ea4af809a: Pull complete
Digest: sha256:8cf9a3e31677df091c148f2b56bcff65663b8768f95ed6a727f29b68a49fa439
Status: Downloaded newer image for redis:alpine
Creating composetest_web_1   ... done
Creating composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 18 Jun 2021 19:23:25.255 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 18 Jun 2021 19:23:25.255 # Redis version=6.2.4, bits=32, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 18 Jun 2021 19:23:25.255 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 18 Jun 2021 19:23:25.265 * monotonic clock: POSIX clock_gettime
redis_1  | 1:M 18 Jun 2021 19:23:25.267 # Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.
redis_1  | 1:M 18 Jun 2021 19:23:25.269 * Running mode=standalone, port=6379.
redis_1  | 1:M 18 Jun 2021 19:23:25.270 # Server initialized
redis_1  | 1:M 18 Jun 2021 19:23:25.270 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1  | 1:M 18 Jun 2021 19:23:25.272 * Ready to accept connections
web_1    |  * Serving Flask app '' (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: This is a development server. Do not use it in a production deployment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: off
web_1    |  * Running on all addresses.
web_1    |    WARNING: This is a development server. Do not use it in a production deployment.
web_1    |  * Running on (Press CTRL+C to quit)

We see that it is running at and in another session I execute several calls to that URL with a curl and we see that the web page's output counter increases with each request:

operatorvm@vmrp01ubuntu2004web:~/composetest$ curl
Hello World! I have been seen 1 times.
operatorvm@vmrp01ubuntu2004web:~/composetest$ curl
Hello World! I have been seen 2 times.
operatorvm@vmrp01ubuntu2004web:~/composetest$ curl
Hello World! I have been seen 3 times.
operatorvm@vmrp01ubuntu2004web:~/composetest$ curl
Hello World! I have been seen 4 times.

Working. And we check by running 'docker ps' the running containers:

operatorvm@vmrp01ubuntu2004web:~/composetest$ docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                    NAMES
f876d87c1136   redis:alpine      "docker-entrypoint.s…"   18 minutes ago   Up 17 minutes   6379/tcp                 composetest_redis_1
1ceab8c84212   composetest_web   "flask run"              18 minutes ago   Up 17 minutes>5000/tcp   composetest_web_1

And we check the images we have with 'docker images':

operatorvm@vmrp01ubuntu2004web:~/composetest$ docker images
REPOSITORY        TAG          IMAGE ID       CREATED          SIZE
composetest_web   latest       041a75134d33   19 minutes ago   129MB
redis             alpine       9cd134b2bbea   47 hours ago     24.8MB
python            3.7-alpine   6c256ee2d829   2 days ago       36.4MB
hello-world       latest       851163c78e4a   17 months ago    4.85kB

It can also be run from a web browser by calling the IP within the local network of the raspberry pi, not the internal which is the virtual network created by docker-compose. This works by specifying the following in the Dockerfile, which allows working on all network interfaces:


In my case, the Raspberry Pi has the IP on my network and from a browser it responds: