Inspired by this post, this weekend I decided to make another attempt at getting ASP.NET Core Web API working under Docker on a Raspberry Pi. I tried this in the past directly on the Raspberry Pi and ran into issues with building the code, which according to that post, still isn’t possible.

Instead of using the public Docker Hub, I wanted to use my own private Docker registry. I already had nimblestratus/rpi-docker-registry running on my Raspberry Pi, but it was very old now and seems to be incompatible with the latest version of Docker I have running on my Mac. I found that the Docker distribution repository on Github contained a Dockerfile for running the registry, but that the version of the base image used by it was incompatible with Raspberry Pi. To fix that, I adjusted the Dockerfile to use the latest version of the golang image (which now has ARM support) and built my own version of the registry image.

git clone https://github.com/docker/distribution ~/docker-distribution
cd $_
sed -i 's/1.8-alpine/1.9.2-alpine/' Dockerfile
docker build -t registry-pi --build-arg GOARCH=arm .

Then start a container with the image:

docker run -d -p 5000:5000 --name registry registry-pi

Confirm that the registry is up and running with:

curl http://localhost:5000/v2/_catalog

I didn’t want to deal with setting up SSL, which Docker requires by default, so back on my Mac I configured Docker to allow an insecure registry. The domain docker.tboyce.com is just a host entry I configured so I would not have to remember the IP address.

insecure-registry

Now that I had the Docker registry up and running, still on my Mac, I basically followed Alex’s instructions for building a console app, but when scaffolding the application, used the following command to create an API instead of a console app:

dotnet new api --name pi-sharp

I had to modify the generated code in Program.cs and add a UseUrls call to listen on all IP addresses:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace pi_sharp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }
        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://*:5000")
                .UseStartup<Startup>()
                .Build();
    }
}

And then built the image with a tag to use my private registry, and pushed the image to the registry:

docker build -t docker.tboyce.com:5000/pi-sharp:0.1 .
docker push docker.tboyce.com:5000/pi-sharp:0.1

Switching over to my Raspberry Pi, I configured it to work with the insecure registry:

sudo -i
echo -e '{\n\t"insecure-registries": ["docker.tboyce.com:5000"]\n}' \
> /etc/docker/daemon.json
service docker restart
exit

And then fired up a container with the image I had pushed (mapping it to port 5001 because 5000 was already in use by the registry):

docker run -d -p 5001:5000 --name pi-sharp \
docker.tboyce.com:5000/pi-sharp:0.1

And tested it out with:

curl http://localhost:5001/api/values

Which printed out the sample values:

api-result1