From 0 to Docker with the PINE64

July 2, 2016 · 5 minute read

In early 2016, I stumbled across the PINE64 Kickstarter. The promised Single Board Computer (SBC) sounded too good to be true. A 64-bit A53 ARM processor, gigabit Ethernet, and 2GB memory, for $30, the same price as a considerably, at the time, less feature-rich Raspberry Pi 2B. Nevertheless, I decided to order two with the idea of using them to experiment with a small cluster. Reading about all the high-profile Kickstarter failures and the ambitious goals of the project, I was even surprised when the boards arrived, on time, without any defects.

Yet, you get what you pay for. Compared to the huge Raspberry Pi resources, the PINE64 is less accommodating with only a couple of community-maintained Linux images. Similarly, there is little documentation on both the hardware as well as getting docker running. So, this post aims to be a general introduction for getting from zero to docker on the PINE64, as well as a reference for myself to avoid any of the pitfalls in the future.

Hardware Setup

Although this post assumes that you know your way around Linux and hardware, this section briefly highlights some of the points that might be useful to prospective owners of a PINE64. First of all, the boards ship without any cables or other peripherals. So in order to be able to easily setup the board as described below, you will at least the following:

  • an Ethernet cable
  • a micro-SD card (size > 8GB, class 10 or higher)
  • a decent micro-USB cable + power supply of at least +5V @ 2A.

For more detailed, extensive requirements see the PINE64 wiki.

A common issue with the board is the power supply. As the board does not provide any (visual) feedback on whether is getting enough power, you should ensure that the power supply has a decent voltage. The red light on the board will be let regardless of whether the system receives enough power to be booted.

Basic Setup

As mentioned before, it is assumed that you are familiar with Linux. So this part of the setup will be a quick walk-through of the steps that are specific to getting a setting up the PINE64 over the network.

1. Flashing the image

First we need to flash a bootable, PINE64-specific Linux image onto the microSD. We are going to use a headless Ubuntu image, as it is, at the moment of writing, the most stable build available. It already contains the essentials, such as ssh, and supports all versions of the PINE64.

  • Download the headless Ubuntu image by Longsleep.
  • In order to do that find out which disk in /dev it is assigned to, using either diskutil list (MacOS) or dh -f (Linux).
  • Copy the contents of the downloaded image to the microSD, using: dd if=<img> of=<disk> bs=1m`, where is the location of the downloaded image and is the location of the disk (in /dev/*). The copying should take a while, hit ctrl+t to view the progress.
  • After the flashing has completed, ensure that you unmount the disk: diskutil unmount <disk> (MacOS) or umount <disk> (Linux).
  • Finally, insert the microSD into the PINE64 and turn on the power.

For Windows or non-terminal-based flashing, see the wiki on flashing images.

2. Basic System Configuration

Now that we have a fully working PINE64 running Ubuntu (ignoring Murphy’s Law), some basic system configuration is needed. In order to do this as a lazy as possible, assuming that board is connected to the LAN by Ethernet (cable), the image already allows for ssh access.

  • Before we can access the board, we need to find out on which IP the board is currently residing. There are various approaches to finding this out, such as looking in the router management console.
  • Now we can ssh into the board using ssh ubuntu@<ip> with the password ubuntu.

Once in the ssh session, there is one important thing to do. The flashed image only uses the predefined size of the OS. In order to be able to use the full SD-card, the filesystem needs to be resized. Luckily, the image contains a helpful script to do this: /usr/local/sbin/ After resizing has completed, be a good citizen, by take a bit of time to update the system: apt-get update && apt-get upgrade.

3. Access Configuration

Now that the essential configuration is done, it is time to make the pine a bit more enjoyable to work with. Instead of using DCHP to assign dynamic IPs to the board, it would be easier to have a single static IP, regardless of any restarts. To do this find /etc/network/interfaces.d/eth0 and replace it with the following:

auto eth0
iface eth0 inet static
        address <lip>
        netmask <mask>
        gateway <gateway>

For decide on some local IP, the correct netmask and the relevant gateway. This depends on the network setup, and can generally be found using `ifconfig` on the host and copying the netmask and gateway and deciding on a local, static IP, such as

To activate these changes run: sudo /etc/init.d/networking restart or reboot.

4. SSH Configuration

Assuming that you have set up a SSH agent on the host machine (if not check out the ssh guide by GitHub), setting up certificate-based authentication prevents you from having to keep remembering and typing the password at login.

  • Copy the ID (public key) to the board ssh-copy-id ubuntu@<ip>.
  • On the board again, the final step is to change the default password: passwd.

Docker Setup

Although Docker has become the defacto standard for deploying, it is still pretty incompatible across platforms and, more importantly, across CPU architectures. To be able to run a Docker image it needs to be compiled specifically for that type of architecture. To complicate things further, Docker for ARM64 is not officially maintained anymore. It currently is maintained by the Ubuntu community, which, nevertheless, makes it lag behind the official releases. To install it:

sudo apt-get install

As mentioned images have to build specifically for arm64 to run on the PINE64. To illustrate, running a x86 docker image, docker run --rm hello-world will trigger an exception in the form of:

write pipe: bad file descriptor

Now if we run a arm64 docker image, it run correctly.

docker run --rm aarch64/hello-world`

There is no way consistent way of finding out which images are arm64 compatible. The only hint that is available is the name of the image. An alternative, promising option seems to be to use qemu, which would allow you to emulate a specific CPU architecture.


The PINE64 definitely has some caveats and pitfalls. The implicit power requirements took some time to figure out. I am also a bit weary of the lifetime of the board, given the complete lack of support of from the company. However, given the price I paid for it at the time, it is a nice board to mess around with.


  • Since writing this blog, Docker has significantly improved its support for ARMv8 architectures.
  • The Raspberry Pi 3 has come out, with comparable specs at a comparable price. Given the community and the long term support, I would definitely recommend it over the PINE64.