Raspbian下安装 Docker 前面已经介绍过,这里不在赘述,不熟悉的可跳转查看:
Raspbian Debian Buster Docker 安装和使用
掌握了树莓派中Docker的安装和基本命令的使用,需要写一个实例熟悉一下使用Docker进行开发的思路,顺便加深一下对Docker的理解。
在开发应用程序时,我们通常会以一个镜像为基础,我们在其上进行定制,这就是基础镜像,基础镜像只是为应用程序提供依赖包。
比如我们要构建一个Python应用的镜像,选择一个Python镜像作为基础镜像会比选择一个普通的系统镜像作为基础镜像更方便一些,因为该镜像预装了Python,并且提供多个不同Python版本的选项。
Docker Hub 上有大量的高质量的官方镜像可以使用。
Raspberrypi是arm架构,arm平台不能使用x86镜像,Raspbian 可使用的镜像可访问 arm32v7。
如 ubuntu、debian、centos、fedora、alpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。
注:Docker镜像的最底层是bootfs(bootloader和kernel),Linux刚启动会加载bootfs文件系统;rootfs在bootfs之上,就是各种不同的操作系统发行版,比如Ubuntu, Centos,Debian等等;平时我们安装进虚拟机的CentOS都是好几个G,在Docker这里才几百甚至才几十M,是因为rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,底层直接调用宿主的kernel
如 node、oraclejdk,openjdk、python、ruby、golang 等,方便开发、构建、运行各种语言应用。
像 Python镜像还会有多种版本,比如Alpine Linux(尺寸超小,缺少Linux环境中的glibc,而采用的musl,编译时间超长)、Debian Buster(基础库完整,尺寸较大,磁盘利用率低)、Debian Buster slim(Debian Buster的“瘦身”版本,尺寸小,磁盘利用率高,缺少通用的包)等
如 nginx、redis、mongo、mysql、tomcat 等
注:tomcat镜像很大,是因为该镜像需要以OS(rootfs)、JDK作为基础
不以任何系统为基础,对于 Linux下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 from scratch 会让镜像体积更加小巧
我们是初次使用,先直接选择 arm32v7/Python镜像 (不过该镜像相较于其它镜像并没有明显的优势,后期再用Debian Buster实现一次)
最开始前需要先掌握 Docker 一些常用命令的使用,后面会用到
命令用于使用 Dockerfile 文件创建镜像
语法:
docker build [OPTIONS] PATH
常用的OPTIONS说明:
-t或者--tag:镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
-f:指定要使用的Dockerfile路径
实例:
# 使用当前目录的Dockerfile创建镜像,注意最后的'.'
# -t 后面的命名规范: dockerid / 名字
docker build -t cooooder/respbiandemo:v1 .
# 使用Dockerfile URL地址创建镜像
docker build cooooder.com/xxxxx/dockerfile-create
# 使用指定位置的Dockerfile文件创建镜像
docker build -f /home/workspace/demo/Dockerfile
语法:
docker run [OPTIONS] IMAGE
常用的OPTIONS说明:
-d:后台运行容器,并返回容器ID
-i:以交互模式运行容器,通常与-t配合使用
-t:为容器重新分配一个伪输入终端
-P:随机端口映射,容器内部端口随机映射到主机的端口
-p:定端口映射,格式为:主机(宿主)端口:容器端口
--name:为容器指定一个名称
-h:指定容器的hostname
-v:主机目录映射容器目录,格式为:主机目录:容器目录
--privileged:容器root提权
实例:
# 使用arm32v7/python:3.9.1-slim-buster镜像
# 后台模式启动一个容器,并将容器命名为raspbian_python
docker run --name raspbian_python -d arm32v7/python:3.9.1-slim-buster
# 后台模式启动一个容器,并将容器的80端口映射到主机随机端口
docker run -P -d arm32v7/python:3.9.1-slim-buster
# 后台模式启动一个容器,将容器的80端口映射到主机的8080端口
docker run -p 8080:80 -d arm32v7/python:3.9.1-slim-buster
# 后台模式启动一个容器,主机的目录/data映射到容器的/data
docker run -v /data:/data -d arm32v7/python:3.9.1-slim-buster
# 交互模式启动一个容器,在容器内执行 bash 命令
docker run -it arm32v7/python:3.9.1-slim-buster bash
实现一个简单的树莓派Python项目,实现呼吸灯效果(LED灯间隔关闭启动)
创建一个raspbian_python项目,根目录下新建主程序文件 led_demo.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Desc: 树莓派4B+(raspbian buster 10)LED demo
Author:Edward
"""
from gpiozero import LED
from time import sleep
from apscheduler.schedulers.blocking import BlockingScheduler
# 引脚接了一个LED小灯泡
# 关于 gpiozero 的使用可以参考API: https://www.cooooder.com/archives/2020122501
led = LED(14)
# LED闪一下
def show(interval_time=1):
led.on()
sleep(interval_time)
led.off()
# 非阻塞 1s闪一次
scheduler = BlockingScheduler()
scheduler.add_job(show, 'interval', seconds=2)
scheduler.start()
# 安装pipreqs,可以实现只导出指定项目下的依赖
pip install pipreqs
# 在项目根目录下执行命令,生成requirements.txt
pipreqs ./ --encoding=utf8
# 运行成功后,在项目根目录下会自动生成requirements.txt
APScheduler==3.6.3
gpiozero==1.5.1
pigpio==1.44
# 基于镜像基础
FROM arm32v7/python:3.9.1-slim-buster
# 设置代码文件夹工作目录 /app
WORKDIR /app
# 复制当前代码文件到容器中 /app
ADD . /app
# 切换国内镜像源
COPY sources.list /etc/apt/sources.list
# 更新软件索引
RUN apt update
# 安装pigpio
RUN apt install -y python3-pip=18.1-5
# 安装所需的包,使用国内源,网络好的可以忽略 -i的一串命令
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
# Run app.py when the container launches
CMD ["python", "led_demo.py"]
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
# 当前目录生成镜像,注意“.”
docker build -t raspbian/pythondemo:1.0.0 .
docker images
# 可以查看到生成的镜像数据
# REPOSITORY TAG IMAGE ID CREATED SIZE
# raspbian/pythondemo 1.0.0 cda481dda20a 10 seconds ago 414MB
docker run --privileged -d raspbian/pythondemo:1.0.0
需要提权运行镜像,否则会报错提示“no module named RPi",LED灯无反应
注:docker容器获取GPIO PIN权限有三种实现方式:“–privileged”,“/dev/gpiomem device”和“sysfs”。
可参考该链接
– 2021/01/07 待解决 –
然而我在使用“–privileged” 操作时,取消-d后台模式,而是直接运行,发现python代码执行其实还是提示“no module named RPi",但是LED灯可以正常闪烁;我以bash模式进入docker手动执行py程序仍是这个情况。这个问题暂停没有找到很好的解释和处理方式,后期找到解决方案再来进行补充。如果有人知道怎么解决可以留言告诉一下我~
# 查看当前运行的容器, -a可以查看所有的容器包括已停止的
docker ps -a
# CONTAINER ID IMAGE COMMAND CREATED STATUS
# a4d3cc87662a raspbian/pythondemo:1.0.0 "python led_demo.py" 1 hour ago Created
# 根据CONTAINER ID停止容器,CONTAINER ID可以只输入前三位
docker stop a4d
# 根据CONTAINER ID删除容器
docker rm a4d
# 查看当前所有镜像
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# raspbian/pythondemo 1.0.0 cda481dda20a 10 seconds ago 414MB
# 根据IMAGE ID删除镜像,IMAGE ID可以只输入前三位,删除镜像前需要把该镜像生成的容器全部删除
docker rmi cda