Raspberry PI Zero (W)에 docker 설치
Synology NAS에 실습을 해 본 김에,
Synology NAS(DS216+II)에 docker 설치 후 .NET Core 2.1 응용 프로그램 실행하는 방법
; https://www.sysnet.pe.kr/2/0/11713
어차피 같은 Linux 계열 운영체제이니 이참에 가지고 있던
Raspberry PI Zero 모델에 docker를 올려봤습니다. 물론, 상세한 문서가 이미 다음과 같이 공개되어 있습니다. ^^
Get Docker CE for Debian
; https://docs.docker.com/install/linux/docker-ce/debian/
중간에 "Install using the repository"에 보면 "Raspbian users cannot use this method!"라고 하면서 "
convenience script"를 사용하라고 합니다. 이름만큼이나... 정말 설치 방법이 간단한데 그냥 다음과 같이 실행해 주면 해당 스크립트 안에서 모든 작업을 알아서 해줍니다.
$ sudo -i
~# curl -sSL https://get.docker.com | sh
# Executing docker install script, commit: 36b78b2
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/raspbian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian stretch edge" > /etc/apt/sou docker.list
+ [ raspbian = debian ]
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sh -c docker version
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:30:52 2018
OS/Arch: linux/arm
Experimental: false
Server:
Engine:
Version: 18.06.1-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:26:37 2018
OS/Arch: linux/arm
Experimental: false
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
sudo usermod -aG docker your-user
Remember that you will have to log out and back in for this to take effect!
WARNING: Adding a user to the "docker" group will grant the ability to run
containers which can be used to obtain root privileges on the
docker host.
Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
for more information.
끝입니다. ^^ 단지, 메시지에 보이는 데로 docker 명령어는 원래 sudo 권한으로 실행해야 하는데 "usermod -aG docker [사용자계정]"으로 추가한 계정에 대해서는 sudo를 붙이지 않아도 docker 명령어를 사용할 수 있으니 원한다면 (편의상) 그렇게 해줍니다.
그런데 라즈베리 파이 제로의 CPU가 armv6l 기반이라서,
$ uname -a
Linux rasp01 4.14.73+ #1148 Mon Oct 1 16:41:23 BST 2018 armv6l GNU/Linux
적절한 docker 이미지를 찾는 것이 쉽지 않습니다. 가령, arm 계열을 위한 hello-world 예제인 듯 보이는 이미지를 실행해도,
$ docker run armhf/hello-world
$
보는 바와 같이 아무런 출력이 없고 container는 그냥 종료된 상태입니다. 검색해 보면 다음의 (답변 없는) 상황과 일치합니다.
Docker run does not display any output
; https://stackoverflow.com/questions/52233182/docker-run-does-not-display-any-output
Rasberry PI Zero도 다음의 명령어 결과로 봐서는 armhf이긴 한 것 같은데,
$ dpkg --print-architecture
armhf
좀 더 찾아 보면,
What is difference between arm64 and armhf?
; https://stackoverflow.com/questions/37790029/what-is-difference-between-arm64-and-armhf
armhf stands for "arm hard float", and is the name given to a debian port for arm processors (armv7+) that have hardware floating point support.
armv7 이후의 모델에 해당한다고 합니다. Rasberry PI Zero의 경우 armv6l이기 때문에 아마도 armhf 접두사가 붙은 docker 이미지들은 실행을 못하는 것 같습니다. 검색해 보면, resin에서 배포하는 이미지들이 그나마 armv6에 대한 것들이 있는 데요,
C:> docker search "Raspberry" --limit 100 --no-trunc
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
homeassistant/raspberrypi3-homeassistant 81
sdthirlwall/raspberry-pi-cross-compiler Raspberry Pi cross-compiler and sysroot in a box. 30 [OK]
resin/raspberrypi3-python The Python buildpack image for Python apps for Raspberry Pi 3. Maintained by Resin.io. 28
resin/raspberrypi3-debian The bare bones OS image for Raspberry Pi 3. Maintained by Resin.io. 20
sdt4docker/raspberry-pi-cross-compiler Raspberry Pi cross-compiler in a box. 19 [OK]
resin/raspberrypi3-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 15
resin/raspberry-pi-alpine-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 12
resin/raspberry-pi-python The Python buildpack image for Python apps for Raspberry Pi v1 & ZERO. Maintained by Resin.io. 11
resin/raspberry-pi-alpine The bare bones Alpine Linux OS image for Raspberry Pi v1 & ZERO. Maintained by Resin.io. 10
resin/raspberrypi2-node This repository is obsolete. 9
homeassistant/raspberrypi2-homeassistant 7
resin/raspberrypi2-python This repository is obsolete. 7
resin/raspberrypi3-alpine-python The Python buildpack image for Python apps. Maintained by Resin.io. 7
resin/raspberrypi3-alpine The bare bones Alpine Linux OS image for Raspberry Pi 3. Maintained by Resin.io. 6
resin/raspberry-pi2-python The Python buildpack image for Python apps for Raspberry Pi 2. Maintained by Resin.io. 5
resin/raspberrypi3-alpine-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 5
resin/raspberrypi2-debian This repository is obsolete. 5
homeassistant/raspberrypi-homeassistant 5
resin/raspberry-pi-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 4
microsoft/iot-hub-c-raspberrypi-build Includes toolchain for building Raspberry Pi C code 4
resin/raspberrypi2-alpine This repository is obsolete. 4
resin/raspberrypi-node This repository is obsolete. 4
demosense/raspberrypi3-opencv Based on resin/raspberrypi3-python:3.6 installed opencv 4
resin/raspberry-pi-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 3
resin/raspberry-pi-debian The bare bones OS image for Raspberry Pi v1 & ZERO. Maintained by Resin.io. 3
homeassistant/raspberrypi3-64-homeassistant 3
resin/raspberrypi-buildpack-deps This repository is obsolete. 3
resin/raspberrypi-python This repository is obsolete. 2
resin/raspberry-pi-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 2
resin/raspberrypi2-buildpack-deps This repository is obsolete. 2
resin/raspberrypi2-alpine-node This repository is obsolete. 2
resin/raspberry-pi3-python This repository is obsolete. 2
resin/raspberry-pi2-debian The bare bones OS image for Raspberry Pi 2. Maintained by Resin.io. 2
resin/raspberrypi-golang This repository is obsolete. 2
resin/raspberry-pi3-node This repository is obsolete. 1
resin/raspberrypi2-alpine-python This repository is obsolete. 1
resin/raspberrypi2-golang This repository is obsolete. 1
resin/raspberry-pi-alpine-python The Python buildpack image for Python apps. Maintained by Resin.io. 1
resin/raspberry-pi-alpine-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 1
resin/raspberry-pi2-alpine-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 1
resin/raspberrypi3-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 1
resin/raspberry-pi2-alpine-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 1
resin/raspberrypi-alpine-python This repository is obsolete. 1
resin/raspberry-pi2-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 1
resin/raspberrypi3-alpine-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 1
resin/raspberry-pi2-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 1
resin/raspberry-pi-alpine-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 1
resin/raspberry-pi2-alpine The bare bones Alpine Linux OS image for Raspberry Pi 2. Maintained by Resin.io. 1
resin/raspberrypi3-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
habridge/ha-bridge-raspberry-pi2 Docker image of ha-bridge (https://github.com/bwssytems/ha-bridge) specialized for Raspberry Pi 2 0
resin/raspberry-pi2-fedora-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 0
resin/raspberrypi2-fedora-node This repository is obsolete. 0
resin/raspberrypi3-fedora Docker builds of Fedora from Resin for Raspberry Pi 3. Maintained by Resin.io. 0
resin/raspberrypi2-fedora-golang This repository is obsolete. 0
resin/raspberrypi3-alpine-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberry-pi2-fedora-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 0
resin/raspberry-pi2-alpine-python The Python buildpack image for Python apps. Maintained by Resin.io. 0
resin/raspberry-pi3-golang This repository is obsolete. 0
jekotia/resin-raspberrypi3-alpine-node resin-raspberrypi3-alpine-node 0 [OK]
resin/raspberry-pi2-fedora Docker builds of Fedora from Resin for Raspberry Pi 2. Maintained by Resin.io. 0
resin/raspberrypi3-fedora-python The Python buildpack image for Python apps. Maintained by Resin.io. 0
resin/raspberrypi2-alpine-buildpack-deps This repository is obsolete. 0
resin/raspberry-pi2-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberrypi3-fedora-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 0
resin/raspberrypi-openjdk This repository is obsolete. 0
resin/raspberrypi3-fedora-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberry-pi-alpine-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberrypi-alpine-golang This repository is obsolete. 0
resin/raspberry-pi2-alpine-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 0
resin/raspberrypi-alpine-buildpack-deps This repository is obsolete. 0
resin/raspberry-pi2-alpine-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberrypi2-alpine-golang This repository is obsolete. 0
resin/raspberry-pi3-alpine-node This repository is obsolete. 0
resin/raspberry-pi-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberrypi3-fedora-node Node.js is a JavaScript-based platform for server-side and networking apps. Maintained by Resin.io. 0
resin/raspberrypi2-alpine-openjdk This repository is obsolete. 0
resin/raspberry-pi2-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 0
resin/raspberry-pi3-alpine-golang This repository is obsolete. 0
resin/raspberrypi3-fedora-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 0
resin/raspberrypi-alpine-node This repository is obsolete. 0
resin/raspberrypi2-fedora-python This repository is obsolete. 0
resin/raspberry-pi2-fedora-buildpack-deps A collection of common dependencies used for installing various modules. Maintained by Resin.io. 0
resin/raspberrypi-alpine This repository is obsolete. 0
resin/raspberry-pi3-alpine-python This repository is obsolete. 0
resin/raspberry-pi2-fedora-python The Python buildpack image for Python apps. Maintained by Resin.io. 0
habridge/ha-bridge-raspberrypi3 Docker image of ha-bridge (https://github.com/bwssytems/ha-bridge) specialized for Raspberry Pi 3 0
resin/raspberrypi2-fedora-buildpack-deps This repository is obsolete. 0
eyigitoglu/raspberrypitest 0
resin/raspberrypi3-alpine-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 0
resin/raspberrypi3-golang Go (golang) is a general purpose, imperative programming language. Maintained by Resin.io. 0
resin/raspberrypi2-openjdk This repository is obsolete. 0
resin/raspberrypi2-fedora This repository is obsolete. 0
raspberrypython/noddyws A noddy web server serving a blank html page with a random background color 0 [OK]
gbevin/raspberry-ci Raspbian Jessie image for running Continuous Integration UI tests with Docker on a Raspberry PI. 0
resin/raspberrypi2-fedora-openjdk This repository is obsolete. 0
resin/raspberry-pi2-ubuntu-node 0
jekotia/resin-raspberrypi3-debian resin-raspberrypi3-debian 0 [OK]
resin/raspberry-pi2-fedora-openjdk OpenJDK is an open-source implementation of the Java Platform, SE. Maintained by Resin.io. 0
resin/raspberrypi3-ubuntu-node 0
resin/raspberry-pi3-alpine-openjdk This repository is obsolete. 0
실제로 "The bare bones OS image for Raspberry Pi v1 & ZERO. Maintained by Resin.io."라고 하는 "resin/raspberry-pi-debian" 이미지를,
resin/raspberry-pi-debian
; https://hub.docker.com/r/resin/raspberry-pi-debian/
실행해 보면,
$ docker run --rm resin/raspberry-pi-debian echo Test
Test
$
저렇게 결과가 출력되는 것을 확인할 수 있습니다.
그렇다면 혹시 .NET Core 응용 프로그램을 실행해 볼 수 있을까요? docker는 CPU의 명령어까지 가상화하는 수준은 아니므로 docker image에 포함된 바이너리 역시 docker 환경이 실행되는 CPU의 제약을 받습니다. .NET Core의 경우 ARM 버전에 포팅된 것이,
.NET Core on Raspberry Pi
; https://github.com/dotnet/core/blob/master/samples/RaspberryPiInstructions.md
armv7 CPU의 명령어 셋을 내포하기 때문에 docker를 이용해도 .NET Core 응용 프로그램을 실행할 수 없습니다.
참고로, docker를 라즈베리 파이가 지원하지 않는 CPU 버전으로 설치하는 경우 다음과 같은 식의 오류가 발생합니다.
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
Traceback (most recent call last):
File "/usr/bin/add-apt-repository", line 95, in <module>
sp = SoftwareProperties(options=options)
File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 109, in __init__
self.reload_sourceslist()
File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 599, in reload_sourceslist
self.distro.get_sources(self.sourceslist)
File "/usr/lib/python3/dist-packages/aptsources/distro.py", line 89, in get_sources
(self.id, self.codename))
aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for Raspbian/stretch
또한, "
Get Docker CE for Debian" 공식 문서에 나온 "https://get.docker.com"의 script가 아니라 "https://download.docker.com/linux/debian"으로부터 "apt-get install docker-ce" 명령어로 직접 설치하려는 경우 다음과 같은 식의 설치 오류가 발생합니다.
$ sudo apt-get -y install docker-ce
Reading package lists... Done
Building dependency tree
Reading state information... Done
docker-ce is already the newest version (18.06.1~ce~3-0~debian).
0 upgraded, 0 newly installed, 0 to remove and 9 not upgraded.
1 not fully installed or removed.
After this operation, 0 B of additional disk space will be used.
Setting up docker-ce (18.06.1~ce~3-0~debian) ...
Job for docker.service failed because a fatal signal was delivered causing the control process to dump core.
See "systemctl status docker.service" and "journalctl -xe" for details.
invoke-rc.d: initscript docker, action "start" failed.
docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: core-dump) since Wed 2018-10-03 12:36:15 KST; 191ms ago
Docs: https://docs.docker.com
Process: 3636 ExecStart=/usr/bin/dockerd -H fd:// (code=dumped, signal=SEGV)
Main PID: 3636 (code=dumped, signal=SEGV)
CPU: 546ms
Oct 03 12:36:15 rasp01 systemd[1]: docker.service: Unit entered failed state.
Oct 03 12:36:15 rasp01 systemd[1]: docker.service: Failed with result 'core-dump'.
Oct 03 12:36:16 rasp01 systemd[1]: docker.service: Service hold-off time over, scheduling restart.
Oct 03 12:36:16 rasp01 systemd[1]: Stopped Docker Application Container Engine.
dpkg: error processing package docker-ce (--configure):
subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
docker-ce
E: Sub-process /usr/bin/dpkg returned an error code (1)
journalctl 명령어로 보면 다음과 같은 로그만 있을 뿐입니다.
$ journalctl -u docker.service
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Main process exited, code=dumped, status=11/SEGV
Oct 03 13:14:35 rasp01 systemd[1]: Failed to start Docker Application Container Engine.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Unit entered failed state.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Failed with result 'core-dump'.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Service hold-off time over, scheduling restart.
Oct 03 13:14:35 rasp01 systemd[1]: Stopped Docker Application Container Engine.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Start request repeated too quickly.
Oct 03 13:14:35 rasp01 systemd[1]: Failed to start Docker Application Container Engine.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Unit entered failed state.
Oct 03 13:14:35 rasp01 systemd[1]: docker.service: Failed with result 'core-dump'.
armhf에 대해 좀 더 찾아 보니,
2.1. 지원하는 하드웨어
; https://www.debian.org/releases/jessie/armhf/ch02s01.html.ko
다음과 같은 설명이 있습니다.
- 데비안/armel은 오래된 32비트 ARM 프로세서로 하드웨어 부동 소수점 기능(FPU)이 없는 프로세서이고,
- 데비안/armhf는 최소한 ARMv7 아키텍쳐를 구현하고 ARM vector floating point specification의 버전3를(VFPv3) 구현한 최근의 ARM 프로세서에서만 동작합니다. 이 모델의 프로세서에 들어 있는 확장된 기능을 사용하므로 성능이 높습니다.
- 데비안/arm64는 최소한 ARMv8 아키텍쳐를 구현한 64비트 ARM 프로세서입니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]