# Build Images for Multiple Platforms

**URL:** https://drone.discourse.group/t/build-images-for-multiple-platforms/11072
**Category:** Drone Support
**Created:** [March 20, 2021, 2:35pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072 "2021-03-20T14:35:54Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![simann](https://yyz1.discourse-cdn.com/flex003/user_avatar/drone.discourse.group/simann/32/2669_2.png) [@simann](https://drone.discourse.group/u/simann)
#### Post date: [March 20, 2021, 2:35pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072/1 "2021-03-20T14:35:54Z")

</div>

Greetings everyone!

I’m trying to automate my builds with Docker, Drone CI and Gitea. I have a basic setup that is working:  
push to Gitea → Drone fetches the latest code and builds an docker image → push to local registry

Im currently in development and testing phase, cuz of this i have everything setup without ssl or any security mechanisms.

I was doing all of this on a pi 3 and recently i got another pi 4 and i moved my compose stack to the pi 4. After this i tried to run the created image on the pi 3 and it failed due to the architecture.

pi 3: arm32v7  
pi 4: arm 64

Now i tried building multiple docker images (arm64, arm32 and maybe amd64) but i didnt have success.

First of all: Is this possible at all?

If not what would be a solution to this case? Setup another drone runner on an pi 3 that then executes the build?

Compose file of my build stack:

```
version: "3.7"
networks:
  gitea:
    name: gitea
    external: false
services:
  registry:
    image: registry:latest
    container_name: registry
    restart: always
    networks:
      - gitea
    ports:
      - 5000:5000
    volumes:
     - ./registry:/var/lib/registry
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - ROOT_URL=http://gitea:3000
      - USER_UID=1000
      - USER_GID=1000
      - DB_TYPE=mysql
      - DB_HOST=database:3306
      - DB_NAME=gitea
      - DB_USER=gitea
      - DB_PASSWD=gitea
    restart: always
    networks:
      - gitea
    depends_on:
      - database
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 3000:3000
      - 22:22
    database:
      container_name: database
    image: mariadb:latest
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=gitea
      - MYSQL_USER=gitea
      - MYSQL_PASSWORD=gitea
      - MYSQL_DATABASE=gitea
    networks:
      - gitea
    ports:
      - 3306:3306
    volumes:
      - ./database:/var/lib/mysql
  drone-server:
    container_name: drone-server
    image: drone/drone:latest
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./drone:/data
      - /var/run/docker.sock:/var/run/docker.sock
    restart: always
    networks:
      - gitea
    depends_on:
      - gitea
    environment:
      - DRONE_GITEA=true
      - DRONE_GITEA_CLIENT_ID=<id>
      - DRONE_GITEA_CLIENT_SECRET=<secret>
      - DRONE_GITEA_SERVER=http://192.168.178.58:3000
      - DRONE_RPC_SECRET=false-horse-worse-staple
      - DRONE_SERVER_HOST=192.168.178.58:80
      - DRONE_SERVER_PROTO=http
      - DRONE_TLS_AUTOCERT=false
      - DRONE_USER_CREATE=username:sf,admin:true
      - DRONE_NETWORK=gitea
      - DRONE_LOGS_TRACE=true
      - DRONE_LOGS_PRETTY=true
      - DRONE_LOGS_COLOR=true
  drone-agent:
    container_name: drone-agent
    image: drone/drone-runner-docker:latest
    ports:
      - 4000:3000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./agent:/data
    restart: always
    networks:
      - gitea
    depends_on:
      - database
      - drone-server
    environment:
      # Runner Server Settings
      - DRONE_RPC_HOST=192.168.178.58:80
      - DRONE_RPC_PROTO=http
      - DRONE_RPC_SECRET=false-horse-worse-staple
       # Runner Settings
      - DRONE_RUNNER_NAME=Dronus
      - DRONE_RUNNER_CAPACITY=1
      - DRONE_RUNNER_NETWORKS=gitea
      # Debug
      - DRONE_DEBUG=true
      - DRONE_LOGS_TRACE=true
      - DRONE_LOGS_PRETTY=true
      - DRONE_LOGS_COLOR=true

```

This is my build pipeline:

```
kind: pipeline
type: docker
name: Build ARM64
platform:
  os: linux
  arch: arm64
steps:
  - name: install and build
    image: node:latest
    pull: if-not-exists
    commands:
      - npm install
      - npm run build
  - name: build docker image
    image: plugins/docker
    pull: if-not-exists
    settings:
      auto_tag: true
      insecure: true
      dockerfile: docker/Dockerfile
      repo: 192.168.178.39:5000/frontend
      registry: 192.168.178.39:5000

---
kind: pipeline
type: docker
name: Build ARM32
platform:
  os: linux
  arch: arm
steps:
  - name: install and build
    image: node:latest
    pull: if-not-exists
    commands:
      - npm install
      - npm run build
  - name: build docker image
    image: plugins/docker
    pull: if-not-exists
    settings:
      auto_tag: true
      insecure: true
      dockerfile: docker/Dockerfile
      repo: 192.168.178.39:5000/frontend
      registry: 192.168.178.39:5000

---
kind: pipeline
type: docker
name: Build AMD64
platform:
  os: linux
  arch: amd64
steps:
  - name: install and build
    image: node:latest
    pull: if-not-exists
    commands:
      - npm install
      - npm run build
  - name: build docker image
    image: plugins/docker
    pull: if-not-exists
    settings:
      auto_tag: true
      insecure: true
      dockerfile: docker/Dockerfile
      repo: 192.168.178.39:5000/frontend
      registry: 192.168.178.39:5000

```

The first Pipeline gets executed without problems, the second is stuck in pending state and never gets executed.

Any hint, help or advice would be appreciated 🙂

---

<div class="post-metadata">

### Author: ![bradrydzewski](https://yyz1.discourse-cdn.com/flex003/user_avatar/drone.discourse.group/bradrydzewski/32/3513_2.png) [@bradrydzewski](https://drone.discourse.group/u/bradrydzewski)
#### Post date: [March 20, 2021, 2:54pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072/2 "2021-03-20T14:54:47Z")

</div>

> [@On another topic](https://drone.discourse.group/t/8877/1):
>
> First of all: Is this possible at all?

Yes, we execute multi-os and multi-arch pipelines for Drone itself. If you look at our git plugin pipeline, for example [1], we execute pipelines for linux/arm, linux/arm64, linux/amd64, and windows/adm64. We also have a dedicated thread that you can use to triage builds stuck in pending status [2] which includes all data that we need to see in order to help you triage.

 ![Screen Shot 2021-03-20 at 10.54.13 AM](https://canada1.discourse-cdn.com/flex003/uploads/testdrone/original/2X/c/c6bbe009aa45a0cbbb064ecaf717a00adcbe2a16.jpeg)

[1] [https://github.com/drone/drone-git/blob/master/.drone.yml](https://github.com/drone/drone-git/blob/master/.drone.yml)  
[2] [http://discuss.harness.io/t/builds-are-stuck-in-pending-status/4437](http://discuss.harness.io/t/builds-are-stuck-in-pending-status/4437)

---

<div class="post-metadata">

### Author: ![simann](https://yyz1.discourse-cdn.com/flex003/user_avatar/drone.discourse.group/simann/32/2669_2.png) [@simann](https://drone.discourse.group/u/simann)
#### Post date: [March 20, 2021, 4:46pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072/3 "2021-03-20T16:46:14Z")

</div>

Im glad that this is possible. It looks like there are some errors with my configuration then.

I followed the link u replied and did what was described.

IMHO the problem could be that i only have 1 runner installed, that is armh64 and thus not able to execute the arm32 or the amd64 pipeline.

Sidenote: im using docker-compose with the config provided in my first post, do i have to specifiy the architecture for the docker runner?  
I followed this article:  
[https://docs.drone.io/runner/docker/installation/linux/](https://docs.drone.io/runner/docker/installation/linux/)

If i understand this correctly the image that compose pulls is arm64

Anyway here are the Logs you requested:

1. Provide your server configuration  
drone-server:  
container\_name: drone-server  
image: drone/drone:latest  
ports:
  - 80:80
  - 443:443  
volumes:
  - ./drone:/data
  - /var/run/docker.sock:/var/run/docker.sock  
restart: always  
networks:
  - gitea  
depends\_on:
  - gitea  
environment:
  - DRONE\_GITEA=true
  - DRONE\_GITEA\_CLIENT\_ID=d7579245-2bc6-4c03-aba2-e9701bdd10d1
  - DRONE\_GITEA\_CLIENT\_SECRET=N8CEu6Yd3EG5X9Hq3yjSYDTH3aIaP49RJZikYmbz4-Q=
  - DRONE\_GITEA\_SERVER=http://192.168.178.58:3000
  - DRONE\_RPC\_SECRET=false-horse-worse-staple
  - DRONE\_SERVER\_HOST=192.168.178.58:80
  - DRONE\_SERVER\_PROTO=http
  - DRONE\_TLS\_AUTOCERT=false
  - DRONE\_USER\_CREATE=username:sf,admin:true
  - DRONE\_NETWORK=gitea
  - DRONE\_LOGS\_TRACE=true
  - DRONE\_LOGS\_PRETTY=true
  - DRONE\_LOGS\_COLOR=true

license: “”  
authn:  
endpoint: “”  
secret: “”  
skipverify: false  
agent:  
disabled: false  
azureblob:  
containername: “”  
storageaccountname: “”  
storageaccesskey: “”  
convert:  
extension: “”  
endpoint: “”  
secret: “”  
skipverify: false  
timeout: 1m0s  
cleanup:  
disabled: false  
interval: 24h0m0s  
running: 24h0m0s  
pending: 24h0m0s  
cron:  
disabled: false  
interval: 30m0s  
cloning:  
alwaysauth: false  
username: “”  
password: “”  
image: “”  
pull: IfNotExists  
database:  
driver: sqlite3  
datasource: /data/database.sqlite  
secret: “”  
legacybatch: false  
datadog:  
enabled: true  
endpoint: [https://stats.drone.ci/api/v1/series](https://stats.drone.ci/api/v1/series)  
token: “”  
docker:  
config: “”  
http:  
allowedhosts: []  
hostsproxyheaders: []  
sslredirect: false  
ssltemporaryredirect: false  
sslhost: “”  
sslproxyheaders: {}  
stsseconds: 0  
stsincludesubdomains: false  
stspreload: false  
forcestsheader: false  
browserxssfilter: true  
framedeny: true  
contenttypenosniff: false  
contentsecuritypolicy: “”  
referrerpolicy: “”  
jsonnet:  
enabled: false  
starlark:  
enabled: false  
logging:  
debug: false  
trace: true  
color: true  
pretty: true  
text: false  
prometheus:  
enableanonymousaccess: false  
proxy:  
addr: [http://192.168.178.39:80](http://192.168.178.39:80)  
host: 192.168.178.39:80  
proto: http  
registration:  
closed: false  
registries:  
endpoint: “”  
password: “”  
skipverify: false  
repository:  
filter: []  
visibility: “”  
trusted: false  
ignore: []  
runner:  
local: false  
image: drone/controller:1  
platform: linux/amd64  
os: linux  
arch: arm64  
kernel: “”  
variant: “”  
machine: 1e5df3ad1731  
capacity: 2  
labels: {}  
volumes: []  
networks: []  
devices: []  
privileged: []  
environ: {}  
limits:  
memswaplimit: 0  
memlimit: 0  
shmsize: 0  
cpuquota: 0  
cpushares: 0  
cpuset: “”  
rpc:  
server: “”  
secret: false-horse-worse-staple  
debug: false  
host: 192.168.178.39:80  
proto: http  
s3:  
bucket: “”  
prefix: “”  
endpoint: “”  
pathstyle: false  
secrets:  
endpoint: “”  
password: “”  
skipverify: false  
server:  
addr: [http://192.168.178.39:80](http://192.168.178.39:80)  
host: 192.168.178.39:80  
port: :80  
proto: http  
pprof: false  
acme: false  
email: “”  
cert: “”  
key: “”  
session:  
timeout: 720h0m0s  
secret: ENm7jXbhJn3dL3vauGxurXswfZmUVoiB  
secure: false  
mappingfile: “”  
status:  
disabled: false  
name: “”  
users:  
create:  
username: sf  
machine: false  
admin: true  
token: “”  
filter: []  
minage: 0s  
validate:  
endpoint: “”  
secret: “”  
skipverify: false  
timeout: 1m0s  
webhook:  
events: []  
endpoint: []  
secret: “”  
skipverify: false  
yaml:  
endpoint: “”  
secret: “”  
skipverify: false  
timeout: 1m0s  
bitbucket:  
clientid: “”  
clientsecret: “”  
skipverify: false  
debug: false  
gitea:  
server: [http://192.168.178.39:3000](http://192.168.178.39:3000)  
clientid: 309840f4-1f6f-4a41-a158-053858e8f316  
clientsecret: hjhHPxdlUptlrKCBNk-yri7xr1ViQi3It52JnObWuKc=  
skipverify: false  
scope:

- repo
- repo:status
- user:email
- read:org  
debug: false  
github:  
server: [https://github.com](https://github.com)  
apiserver: [https://api.github.com](https://api.github.com)  
clientid: “”  
clientsecret: “”  
skipverify: false  
scope:
- repo
- repo:status
- user:email
- read:org  
ratelimit: 0  
debug: false  
gitlab:  
server: [https://gitlab.com](https://gitlab.com)  
clientid: “”  
clientsecret: “”  
skipverify: false  
debug: false  
gogs:  
server: “”  
skipverify: false  
debug: false  
stash:  
server: “”  
consumerkey: “”  
consumersecret: “”  
privatekey: “”  
skipverify: false  
debug: false

1. Provide your agent configuration  
drone-agent:  
container\_name: drone-agent  
image: drone/drone-runner-docker:latest  
ports:

2. Provide the agent logs with trace enabled

time=“2021-03-20T16:17:50Z” level=debug msg=“successfully pinged the docker daemon”  
time=“2021-03-20T16:17:50Z” level=info msg=“starting the server” addr=":3000"  
time=“2021-03-20T16:17:50Z” level=info msg=“successfully pinged the remote server”  
time=“2021-03-20T16:17:50Z” level=info msg=“polling the remote server” arch=arm64 capacity=1 endpoint=“[http://192.168.178.39:80](http://192.168.178.39:80)” kind=pipeline os=linux type=docker  
time=“2021-03-20T16:17:50Z” level=debug msg=“poller: request stage from remote server” thread=1  
time=“2021-03-20T16:18:20Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:19:00Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:19:27Z” level=debug msg=“stage received” stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:19:27Z” level=debug msg=“stage accepted” stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:19:27Z” level=debug msg=“stage details fetched” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:19:27Z” level=debug msg=“updated stage to running” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:19:38Z” level=debug msg=“received exit code 0” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 step.name=clone thread=1  
time=“2021-03-20T16:19:57Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:20:37Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:21:17Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:21:57Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:22:37Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:23:17Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:23:57Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:24:37Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:24:40Z” level=debug msg=“received exit code 0” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 step.name=“install and build” thread=1  
time=“2021-03-20T16:25:17Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:25:57Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:25:58Z” level=debug msg=“received exit code 0” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 step.name=“build docker image” thread=1  
time=“2021-03-20T16:25:58Z” level=debug msg=“destroying the pipeline environment” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:26:02Z” level=debug msg=“successfully destroyed the pipeline environment” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:26:02Z” level=debug msg=“updated stage to complete” build.id=16 build.number=14 duration=391 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:26:02Z” level=debug msg=“poller: request stage from remote server” thread=1  
time=“2021-03-20T16:26:07Z” level=trace msg=“http: context canceled”  
time=“2021-03-20T16:26:07Z” level=debug msg=“done listening for cancellations” build.id=16 build.number=14 repo.id=2 repo.name=frontend repo.namespace=sf stage.id=22 stage.name=build-arm64 stage.number=1 thread=1  
time=“2021-03-20T16:26:32Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:27:12Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:27:52Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:28:32Z” level=trace msg=“http: no content returned: re-connect and re-try”  
time=“2021-03-20T16:29:12Z” level=trace msg=“http: no content returned: re-connect and re-try”

1. Provide the server logs with trace enabled

2. Provide the Yaml configuration file

kind: pipeline  
type: docker  
name: build-arm64

platform:  
os: linux  
arch: arm64

steps:

- name: install and build  
image: node:latest  
pull: if-not-exists  
commands:

- name: build docker image  
image: plugins/docker  
pull: if-not-exists  
settings:  
auto\_tag\_suffix: linux-arm64  
auto\_tag: true  
insecure: true  
dockerfile: docker/Dockerfile  
repo: 192.168.178.39:5000/frontend  
registry: 192.168.178.39:5000

* * *

kind: pipeline  
type: docker  
name: build-arm32

platform:  
os: linux  
arch: arm

steps:

- name: install and build  
image: node:latest  
pull: if-not-exists  
commands:

- name: build docker image  
image: plugins/docker  
pull: if-not-exists  
settings:  
auto\_tag\_suffix: linux-arm  
auto\_tag: true  
insecure: true  
dockerfile: docker/Dockerfile  
repo: 192.168.178.39:5000/frontend  
registry: 192.168.178.39:5000

1. Provide the build details for your pending builds via this 124 API endpoint  
// [http://192.168.178.39/api/repos/sf/frontend/builds/14](http://192.168.178.39/api/repos/sf/frontend/builds/14)

---

<div class="post-metadata">

### Author: ![bradrydzewski](https://yyz1.discourse-cdn.com/flex003/user_avatar/drone.discourse.group/bradrydzewski/32/3513_2.png) [@bradrydzewski](https://drone.discourse.group/u/bradrydzewski)
#### Post date: [March 20, 2021, 11:16pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072/4 "2021-03-20T23:16:49Z")

</div>

> [@On another topic](https://drone.discourse.group/t/8877/3):
>
> the problem could be that i only have 1 runner installed, that is armh64 and thus not able to execute the arm32 or the amd64 pipeline.

This is correct, you cannot run arm builds on an amd64 machine. You would need 3 different servers. 1 amd64 server with 1 drone runner installed, 1 arm32 server with 1 drone runner installed, and 1 arm64 server with 1 drone runner installed.

> [@On another topic](https://drone.discourse.group/t/8877/3):
>
> im using docker-compose with the config provided in my first post, do i have to specifiy the architecture for the docker runner?

no, docker pulls the appropriate image for your architecture. If you pull drone/drone-runner-docker on arm64, for example, docker will ensure it pulls the arm64 version of that image.

---

<div class="post-metadata">

### Author: ![simann](https://yyz1.discourse-cdn.com/flex003/user_avatar/drone.discourse.group/simann/32/2669_2.png) [@simann](https://drone.discourse.group/u/simann)
#### Post date: [March 21, 2021, 4:34pm UTC](https://drone.discourse.group/t/build-images-for-multiple-platforms/11072/5 "2021-03-21T16:34:49Z")

</div>

Thanks for your assistance and sorry for the inconvenience.

I set up a runner on 2 different machines with the corresponding platform and everything worked!

Problem solved! Im now going to continue my journey with drone io. 😃

Thank you very much for the quick help and response. 🙂
