【ラズパイでもDocker!】Docker Alpineコンテナ上のNode.jsネイティブアプリからラズパイのGPIOを操作する方法
※ 当ページには【広告/PR】を含む場合があります。
2020/05/08
Nodejs
Nodejs
npmパッケージの利用① 〜 onoff編
nodejs
alpine
nodejs13+alpine3.11
arm32v7/node:alpine
alpine
nodejs
$ docker pull arm32v7/node:alpine
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
arm32v7/node alpine 30bb03f6ec2e 6 months ago 96.6MB
armhf/alpine latest 15ed6d4bf10d 2 years ago 3.6MB
Broadcom BCM2837
Cortex-A53
ARMv8
ARMv8
ARMv7
不足のapkパッケージ追加
arm32v7/node:alpine
onoff
-v /sys:/sys
$ docker run -it \
--rm \
-v /sys:/sys \
arm32v7/node:alpine /bin/sh
onoff
$ apk add --update python make g++
node-gyp rebuild
npmプロジェクトの作成
index.js
/usr/local/app
$ mkdir /usr/local/app && cd /usr/local/app
#👇新規のpackage.jsonを発行
$ npm init -y
Wrote to /usr/local/app/package.json:
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
#👇index.jsがアプリのエントリーポイント
$ touch index.js
$ ls
index.js package.json
onoff
$ npm i onoff
> epoll@4.0.0 install /usr/local/app/node_modules/epoll
> node-gyp rebuild
make: Entering directory '/usr/local/app/node_modules/epoll/build'
CXX(target) Release/obj.target/epoll/app/epoll.o
SOLINK_MODULE(target) Release/obj.target/epoll.node
COPY Release/epoll.node
make: Leaving directory '/usr/local/app/node_modules/epoll/build'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN src@1.0.0 No description
npm WARN src@1.0.0 No repository field.
+ onoff@6.0.0
added 6 packages from 12 contributors and audited 6 packages in 26.364s
found 0 vulnerabilities
onoff
Lチカ
index.js
const { Gpio } = require('onoff');
// GPIO2を出力設定で利用
const ledOut = new Gpio('2', 'out');
// LEDの状態(false=消灯)
let isLedOn = false;
// 一定時間間隔でループ処理
setInterval(() => {
ledOut.writeSync( isLedOn ? 0 : 1 ); // 1の書き込みで点灯・0で消灯
isLedOn = !isLedOn; // 状態を反転
}, 500); // 0.5秒
$ node index.js
#...ずっとチカチカ
cntl + c
余談 ~ --deviceオプションだけだとonoffは動かない
--device /dev/gpiomem
onoff
--device
$ docker run -it \
--rm \
--device /dev/gpiomem \
arm32v7/node:alpine /bin/sh
index.js
$ node index.js
internal/fs/utils.js:220
throw err;
^
Error: EROFS: read-only file system, open '/sys/class/gpio/export'
at Object.openSync (fs.js:440:3)
at Object.writeFileSync (fs.js:1281:35)
at exportGpio (/usr/local/app/node_modules/onoff/onoff.js:18:8)
at new Gpio (/usr/local/app/node_modules/onoff/onoff.js:172:36)
at Object.<anonymous> (/usr/local/app/index.js:4:16)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1103:10)
at Module.load (internal/modules/cjs/loader.js:914:32)
at Function.Module._load (internal/modules/cjs/loader.js:822:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1143:12) {
errno: -30,
syscall: 'open',
code: 'EROFS',
path: '/sys/class/gpio/export'
}
onoff
/sys/class/gpio
--device
onoff
onoff
npmパッケージの利用② 〜 pigpio編
pigpio
FROM arm32v7/node:alpine
RUN apk update && \
apk upgrade && \
apk add --no-cache python make g++ alpine-sdk unzip bash
RUN wget https://github.com/joan2937/pigpio/archive/master.zip && \
unzip master.zip && \
cd pigpio-master && \
sed -i 's,ldconfig,,' Makefile && \
make && \
make install
WORKDIR /usr/local/app
COPY package.json /usr/local/app
COPY index.js /usr/local/app
RUN npm install
taconocat/pigpio
$ docker build . -t taconocat/pigpio
$ docker run -it \
--rm \
--privileged \
taconocat/pigpio /bin/bash
--privileged
index.js
package.json
index.js(エントリーポイント)
const Gpio = require('pigpio').Gpio;
const led = new Gpio(2, {mode: Gpio.OUTPUT});
let isLedOn = false;
// 一定時間間隔でループ処理
setInterval(() => {
if (isLedOn) {
led.digitalWrite(1);
} else {
// led.off();
led.digitalWrite(0);
}
isLedOn = !isLedOn; // 状態を反転
}, 1000); // 0.5秒
package.json
{
"name": "pigpio-master",
"version": "1.0.0",
"description": "pigpio is a C library for the Raspberry which allows control of the General Purpose Input Outputs (GPIO).",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pigpio": "^3.2.1"
}
}
node index.js
余談 〜 特権コンテナにしないと動かない?
--device
--device
--cap-add
--device
$ docker run -it \
--rm \
--cap-add SYS_ADMIN \
--device /dev/gpiomem \
taconocat/pigpio /bin/bash
node
$ node index.js
2020-05-07 16:13:07 initCheckPermitted:
+---------------------------------------------------------+
|Sorry, you don't have permission to run this program. |
|Try running as root, e.g. precede the command with sudo. |
+---------------------------------------------------------+
/usr/local/app/pigpio-master/node_modules/pigpio/pigpio.js:29
pigpio.gpioInitialise();
^
Error: pigpio error -1 in gpioInitialise
at initializePigpio (/usr/local/app/pigpio-master/node_modules/pigpio/pigpio.js:29:12)
at new Gpio (/usr/local/app/pigpio-master/node_modules/pigpio/pigpio.js:133:5)
at Object.<anonymous> (/usr/local/app/pigpio-master/index.js:3:13)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
node
--previliged
特権コンテナ
--previliged
本番用のプロセス実行コンテナ
FROM arm32v7/node:alpine
RUN apk update && \
apk upgrade && \
apk add --no-cache --virtual build-deps python make g++ alpine-sdk unzip
RUN cd /tmp && \
wget https://github.com/joan2937/pigpio/archive/master.zip && \
unzip -qq master.zip && \
cd pigpio-master && \
sed -i 's,ldconfig,,' Makefile && \
make && \
make install && \
rm -rf /tmp/*
WORKDIR /usr/local/app
COPY package.json /usr/local/app
COPY index.js /usr/local/app
RUN npm install && \
apk del build-deps
CMD ["node", "index.js"]
#デタッチモードで起動
$ docker run -d --privileged taconocat/pigpio
#起動デーモンに登録し常駐化
$ docker update --restart=always taconocat/pigpio
まとめ
記事を書いた人
ナンデモ系エンジニア
電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。
カテゴリー