📝 はじめに
Raspberry Pi 上の Docker コンテナから I2C デバイス(BME280 環境センサー)にアクセスし、温度・湿度・気圧データを収集する環境構築方法を解説します。
対象読者
- Raspberry Pi で IoT 開発を始めたい人
- Docker でハードウェア制御をしたい人
前提条件
- Raspberry Pi OS インストール済み、Docker / Docker Compose インストール済み
- I2C が有効化済み(
raspi-configで設定)
🎯 背景・動機
室内の温度・湿度・気圧をモニタリングするシステムを構築したいと考えました。Docker を採用することで、環境の再現性とメンテナンス性を確保できます。ただし、Docker コンテナからハードウェアにアクセスするには特別な設定が必要です。
🛠️ 手順
1. ハードウェア接続
BME280 センサーを Raspberry Pi の I2C バスに接続します。
| BME280 | Raspberry Pi |
|---|---|
| VCC | 3.3V (Pin 1) |
| GND | GND (Pin 6) |
| SDA | GPIO 2 / SDA (Pin 3) |
| SCL | GPIO 3 / SCL (Pin 5) |
接続後、i2cdetect -y 1 で 0x76 に BME280 が認識されることを確認します。
2. Dockerfile(マルチステージビルド)
# 開発環境
FROM python:3.10 AS develop
RUN apt-get update && apt-get install -y tzdata python3-pip i2c-tools && apt-get clean
RUN pip3 install poetry && poetry config virtualenvs.create false
ENV TZ=Asia/Tokyo
WORKDIR /workspaces
# 本番環境(軽量化)
FROM python:3.10 AS production
RUN apt-get update && apt-get install -y i2c-tools && apt-get clean
WORKDIR /workspaces
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages/
COPY --from=builder /workspaces/server /workspaces/server
ENV TZ=Asia/Tokyo
CMD [ "/usr/local/bin/python3", "-u", "server/app.py" ]
3. compose.yml(デバイスマウント設定)
Docker コンテナから I2C/GPIO にアクセスするための設定が重要です。
services:
python-dev:
build:
context: .
dockerfile: Dockerfile
target: develop
volumes:
- ./:/workspaces:cached
ports:
- "5010:5010"
# ハードウェアデバイスのマウント
devices:
- /dev/i2c-1:/dev/i2c-1 # I2C(BME280接続)
- /dev/gpiomem:/dev/gpiomem # GPIO
privileged: true # 特権モード
# グループ権限の追加(環境に応じてID確認: cat /etc/group | grep i2c)
group_add:
- "988" # i2c group
- "997" # gpio group
4. BME280 センサー読み取りコード
import board
import adafruit_bme280.advanced as adafruit_bme280
class SensorClient:
def __init__(self):
self.bme280 = None
def init_sensor(self):
try:
i2c = board.I2C()
self.bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)
self.bme280.mode = adafruit_bme280.MODE_NORMAL
self.bme280.iir_filter = adafruit_bme280.IIR_FILTER_X16
return True
except Exception as e:
print(f'センサー初期化失敗: {e}')
return False
def read_sensor_data(self):
if self.bme280:
return {
'temperature': round(self.bme280.temperature, 2),
'pressure': round(self.bme280.pressure, 2),
'humidity': round(self.bme280.humidity, 2)
}
return None
必要なライブラリ: adafruit-blinka, adafruit-circuitpython-bme280
🚨 つまずきポイント
グループ ID の確認方法
$ cat /etc/group | grep -E "(i2c|spi|gpio)"
Raspberry Pi OS のグループ ID はディストリビューションによって異なる場合があります。
センサー未接続時のフェイルセーフ
本番環境でセンサーが接続されていない場合に備え、ダミーデータモードを実装しておくと開発・テストが容易になります。
📝 まとめ
-
Docker でもハードウェアアクセスは可能:
devicesマウントとprivilegedモードで I2C/GPIO にアクセスできる - マルチステージビルドの効果: 開発環境と本番環境を分離し、本番イメージサイズを削減
- Adafruit CircuitPython の使いやすさ: 豊富なセンサー対応ライブラリで素早く実装可能