How I built a multi-arch image to run in zCX
Tags: zos, zcx, docker, buildx
Published: 2020-01-25 21:21:37

---
title: How I built a multi-arch image to run in zCX
published: true
description: The steps required to take an existing Docker image and build it for running in zCX
tags: z/OS, zCX, Docker, buildx
---
The latest version of z/OS (2.4) has added a really cool new feature called [__z/OS Container Extensions__](https://www.ibm.com/support/z-content-solutions/container-extensions/) (zCX) which allows you to run Docker containers built for Linux on Z alongside existing z/OS applications on the same LPAR. Having got access to a system I was keen to try and get a simple Liberty application running to try it out.

I already had the Dockerfile and all the components on my local machine ready to build a local image so needed to convert that into a multi-arch image build workflow which could then be pushed to a local registry and run on the zCX appliance. This seemed easier that trying to recreate my development environment on the remote machine and running the Docker commands locally there.

Needing to keep everything in house I needed an image registry to store the multi-arch images. This is easy to set-up for development testing by running a container containing the registry itself. Issuing the following command in the zCX instance brings up the registry

```
docker run -d -p 5000:5000 --restart=always ibmcom/registry-s390x:2.6.2.5
```

(Note: there isn’t an image tagged with `latest` so ensure you add a version onto the image name)

Building multi-arch images is possible with the latest version of Docker Desktop that I had on my laptop, just so long as I had the experimental features turned on. 

![Docker preferences with experimental enabled](https://thepracticaldev.s3.amazonaws.com/i/ae0abtjwg9h2yyqccgnw.png)

With all this in place the [`docker buildx`](https://docs.docker.com/engine/reference/commandline/buildx/) group of commands is available which does all the work for us.

As the registry I created was a simple development one with no security, the image builder needed to be configured to know that http should be used for communication with it rather than https. This configuration is managed in a toml configuration file which I needed to create.

```toml
[registry.”zcxmachine:5000”]
  http = true
```

(Note: I had to use spaces to indent the properties as tabs didn’t seem to work)

Now it was time to get the builder ready to build the image. The default builder will only create images for your local machine so I had to create a new one using the command:

```
docker buildx create --name mybuilder --config=/path/to/config.toml
```

Once this completed then it needed to be set as the one to use.

```
docker buildx use mybuilder
```

Alternatively I could have added the `--use` flag to the create command to create and set as default in one go.

The builder then needed to be initialised 
	
```
docker buildx inspect —bootstrap
```

Checking output showed the platforms that can now be built for, which includes linux/s390x

```
[+] Building 7.4s (1/1) FINISHED
 => [internal] booting buildkit                                                                7.3s
 => => pulling image moby/buildkit:buildx-stable-1                                             3.0s
 => => creating container buildx_buildkit_mybuilder0                                           4.3s
Name:   mybuilder
Driver: docker-container

Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Platforms: linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
```

Now it was possible to build the image and push it to the local registry. So in the directory containing the Docker file I ran this command which specified the platforms to build for and to push the resulting images to the registry.

```
docker buildx build --platform linux/amd64,linux/s390x -t zcxmachine:5000/image:latest . --push
```

With the image now successfully built and pushed to the registry it could be run on the zCX appliance in the standard way.

```
docker run localhost:5000/image:latest
```

Now that I’ve managed to build an image off the machine where the containers need to run the next step will be building this into a CI/CD pipeline and automating as much as possible.