Docker
本⽂主要介绍了 Docker 的基本使⽤⽅式,同时提供编译 SDK 的 Docker 镜像环境的构建⽅式,并针对使⽤过程中的常⻅问题进⾏总结,提供解决⽅法参考。
1. Docker 介绍
Docker 是⼀个旨在让使⽤容器更轻松地创建、部署和运⾏应⽤程序的⼯具。Docker 容器允许开发⼈员将应⽤程序及其所需的所有部分打包在⼀起,例如库和其他依赖项,并将其作为⼀个包发送出去。通过这样做,开发⼈员可以放⼼,该应⽤程序将在任何其他 Linux 设备上运⾏,⽽不管该设备可能具有的⽤于与编写和测试代码的机器不同的任何⾃定义设置。在某种程度上,Docker 有点像虚拟机。但与虚拟机不同的是,Docker 不是创建⼀个完整的虚拟操作系统,⽽是允许应⽤程序使⽤与它们运⾏的系统相同的 Linux 内核,并且只需要应⽤程序附带尚未在主机上运⾏的组件。这显着提⾼了性能并减⼩了应⽤程序的⼤⼩。更重要地是,Docker 是 开源的。这意味着任何⼈都可以为 Docker 做出贡献并扩展它以满⾜⾃⼰的需求。
Dockerfile、Image(镜像)和Container(容器)为Docker中的三个重要概念。通过Image我们可以创建许多个Container,通过Dockerfile这个自动化脚本可以创建Image。
Dockerfile:中文名叫镜像描述文件,是一个包含用于组合镜像目录的文本文档,也可以叫“脚本”。用户通过docker build命令,读取Dockerfile中的指令安装步骤自动生成镜像。
Image:是一个文件系统,提供了容器运行时需要用到的文件和参数配置。相当于平时在使用某个软件时需要下载的安装包,也相当于安装操作系统时需要用到 ISO 文件。
Container:是一种打包软件的方式,因为它不依赖于环境。 应用程序的所有代码、库和依赖配置项都打包到 容器 中。 与虚拟机不同,容器不是创建一个完整的虚拟操作系统,而是允许应用程序使用与它们正在运行的系统相同的 Linux 内核,并且只需要应用程序与尚未在主机上运行的东西一起交付。
更多Rockchip Docker可以参考第三⽅⽹站Rockchip Docker
2. 如何在RK平台上使用 Docker
2.1 Kernel 配置
Docker 运⾏需要 kernel 开启 cgroups、namespace、netfilter、overlayfs 等功能的⽀持,请确保你所使⽤的配置已经满⾜ docker 运⾏的要求。宿主机上可以通过脚本(/usr/share/docker.io/contrib/check-config.sh)进⾏检查,如果系统上没有该脚本,可以通过check-config.sh获取。
另外,我们还提供了通用的 Docker 配置,可以在SDK中通过以下命令进行配置:
make ARCH=arm64 rockchip_linux_defconfig rockchip_linux_docker.config
2.2 Debian 系发行版
2.2.1 安装 Docker
在 Debian系(debian、ubuntu、Kylin、UOS等)发行版 Linux 系统中,我们可以通过以下命令来安装 Docker:
sudo apt-get update # 更新软件包列表
sudo apt-get install docker.io # 安装 Docker,安装的时间可能有一点长,请耐心等待
需要注意 Debian 默认使⽤ iptables-nft,⽽ docker 默认使⽤ iptables-legacy,故需要配置 iptables 使⽤ legacy 版本,可以通过以下命令进⾏切换:
# 使⽤ iptables-legacy
update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
# 使⽤ iptables-nft
update-alternatives --set iptables /usr/sbin/iptables-nft
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft
2.2.2 验证 Docker
验证安装是否成功:
docker --version # 查看 Docker 版本
如果安装成功,会显示 Docker 的版本信息。
Docker version 20.10.24, build 3967b7d
2.3 Relhat 系发⾏版
2.3.1 安装 Docker
在 Relhat系( Redhat、fedora、centos、OpenEuler等)发行版 Linux 系统中,我们可以通过以下命令来安装 Docker:
sudo yum update # 更新软件包列表
sudo yum install docker # 安装 Docker 或者 sudo dnf install docker
2.3.2 验证 Docker
验证安装是否成功:
docker --version # 查看 Docker 版本
如果安装成功,会显示 Docker 的版本信息。
Docker version 20.10.24, build 3967b7d
2.4 Buildroot
2.4.1 配置 Buildroot 启用 Docker 支持
Buildroot 默认不开启 docker 相关配置,如需要 docker 相关功能,可以开启以下配置:
BR2_PACKAGE_CGROUPFS_MOUNT=y
BR2_PACKAGE_DOCKER_ENGINE=y
BR2_PACKAGE_DOCKER_ENGINE_EXPERIMENTAL=y
BR2_PACKAGE_DOCKER_ENGINE_STATIC_CLIENT=y
BR2_PACKAGE_DOCKER_ENGINE_DRIVER_BTRFS=y
BR2_PACKAGE_DOCKER_ENGINE_DRIVER_DEVICEMAPPER=y
BR2_PACKAGE_DOCKER_ENGINE_DRIVER_VFS=y
2.4.2 构建系统
配置完成后,开始构建系统:
cd /path/to/buildroot
make # 开始编译,这可能需要一些时间
2.4.3 部署和配置
构建完成后,将生成的镜像烧录到目标设备。启动系统后,执行以下命令配置 Docker:
# 创建docker用户组
groupadd docker
# 将默认用户添加到docker组(假设用户名为root)
usermod -aG docker root
# 启动Docker服务
/etc/init.d/S40docker start # 或使用systemctl:systemctl start docker
# 设置Docker开机自启
ln -s /etc/init.d/S40docker /etc/rc.d/rcS # 或使用systemctl:systemctl enable docker
2.4.4 验证安装
测试 Docker 是否正常工作:
docker run hello-world # 运行一个测试容器
如果一切正常,你应该能够看到 Docker 输出的欢迎信息。
2.4.5 注意事项
Buildroot 默认可能使用vfs存储驱动,这在生产环境中性能不佳。建议使用overlay2驱动,但需要额外配置内核支持。
Docker 需要足够的内存资源。在资源受限的嵌入式系统中,可能需要调整内存分配。
确保系统网络配置正确,Docker 可能需要桥接网络支持。
2.5 其他发行版
如果您的 Linux 发行版不在上述列表中,您可以参考 Docker 官方文档来获取适用于您发行版的安装指南。
3. 常用命令说明
3.1 创建镜像
# $name:$tag 镜像名称:标签名称
# Dockfile 基于上下⽂构建,构建⽬录必须包含Dockerfile
# $dockerfile 指定 Dockerfile 名称,默认是 PATH/Dockerfile
# $dockerfile_dir Dockerfile 所在路径是 PATH
sudo docker build -f $dockerfile -t $name:$tag $dockerfile_dir
3.2 删除镜像或者容器
# $imageID 镜像ID
sudo docker rmi $imageID
# $containerID 容器ID
sudo docker rm $containerID
3.3 重命名镜像或者容器
# $imageID 镜像ID
# $name:$tag 镜像名称:标签名称
sudo docker tag $imageID $name:$tag
# $containerID 容器ID
# $name 容器名称
sudo docker rename $containerID $name
3.4 查看镜像或者容器
sudo docker image ls # 查看镜像
sudo docker container ls # 查看容器
3.5 运行 Docker 环境
# 运⾏ Docker 环境
# --privileged 特权模式
# -it 表⽰开启交互模式, /bin/bash 表⽰交互⽅式
# -v $host_dir:$docker_dir 将主机⽬录映射到 Docker 内
# -p $host_port:$docker_port 将主机端⼝映射到 Docker 内
# -u $docker_user 指定使⽤ Docker 内⽤⼾登陆
# -w $cwd_dir 切换到容器内的路径
# -d --detach 设置后台运⾏模式
# 运⾏指定的镜像
sudo docker run --privileged -it -u $docker_user -v $host_dir:$docker_dir
$imageID /bin/bash
# 运⾏指定的容器
sudo docker exec -it -w $cwd_dir $containerID /bin/bash
3.6 Docker 镜像管理
# 登录 dockerhub 账号
sudo docker login -u $username -p $password
# 拉取 dockerhub 镜像
sudo docker image pull $imageID
# 推送镜像到 dockerhub
sudo docker image push $username/$imagename
# 导出本地镜像(tar archive file)
sudo docker image save $name:$tag -o ${dockerimage.tar}
# 导⼊本地镜像(tar archive file)
sudo docker image load -i ${dockerimage.tar}
# 本地镜像提交修改
# -m 提交的描述信息
# -a 提交的作者
# $containerID 发⽣修改的容器ID
# $new_name:$new_tag 提交后的镜像名称标签
sudo docker commit -m $commit_message -a $author $containerID $new_name:$new_tag
4. Docker 使用指南
本节介绍基于Ubuntu系统的Docker使⽤指南,其他发行版的使⽤指南可参考 Docker 官方文档。
4.1 安装Docker
使⽤此命令安装最新版本的 Docker(在 ubuntu 14.04 中将 docker 替换为docker.io)
sudo apt-get install docker qemu-user-static binfmt-support
开始运⾏ Docker 守护进程:
sudo service docker start
通过 dockerfile 构建 Docker 镜像:
sudo docker build -t rockchip
通过以上几个步骤即可得到⼀个名为“rockchip”的 Docker 镜像,其中包含⼀个 Debian 多架构交叉编译环境。
4.2 构建应用
进⼊Docker环境
sudo docker run -it -v <package_dir>:/home/rk/packages rockchip /bin/bash
开始构建 对于 ARM 32位芯⽚:
cd /home/rk/packages/<pkg_dev>
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -rfakeroot -b -d -uc -us -aarmhf
ls ../ | grep *.deb
对于 ARM 32位芯⽚:
cd /home/rk/packages/<pkg_dev>
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -rfakeroot -b -d -uc -us -aarm64
ls ../ | grep *.deb
4.3 修改Docker镜像
如果您想要修改 Docker 镜像,可以通过下⾯的命令:
sudo docker run -it rockchip /bin/bash
从容器退出后,使⽤如下的命令来保存你的更改。
sudo docker commit <container_id> rockchip
4.4 实例
如何在 libmali上⽣生 libmali-bifrost-g52-g2p0-x11_1.9-1_arm64.deb
~/work/docker/docker-rockchip$sudo service docker start
~/work/docker/docker-rockchip$sudo docker build -t rockchip 。
~/work/docker/docker-rockchip$sudo docker run -it -v
/home/wxt/work:/home/rk/packages rockchip /bin/bash
rk@2888134f9c12:/$ cd /home/rk/packages/docker/libmali
rk@2888134f9c12:~/packages/docker/libmali$ DEB_BUILD_OPTIONS=nocheck dpkg
buildpackage -rfakeroot -b -d -uc -us -aarm64
上述步骤将获得 ~/packages/docker/ 的 debs
4.5 第三⽅仓库编译⽣成 deb 包
5. 如何使⽤ Docker 编译 SDK
5.1 构建 Docker 镜像
5.1.1 使⽤ Dockerfile 构建
# 参考该⽂档提供的 Dockerfile
# 假设 Dockerfile 位于 /home/docker/Dockerfile
cd /home/docker
sudo docker build -t docker_rk:latest
5.1.2 使⽤提供的镜像
Docker 镜像可从网址 docker 获取
5.2 使⽤ Docker 编译
# 假设 SDK 位于 /home/user/sdk
# 将 SDK 映射到 Docker 镜像内,并进⼊镜像内
sudo docker run --privileged -it -u rk -v /home/user/sdk:/home/rk/sdk
docker_rk:latest /bin/bash
# 切换到 Docker 内的路径,编译⽅法可以通过 build.sh -h 查看
cd /home/rk/sdk
./build.sh -h
5.3 更新 Docker 镜像
# 退出 Docker 镜像后,除映射⽬录外的所有修改都不会保留,要保留相应修改需要更新 Docker 镜像
# 假定本次镜像实例化的容器为 rk@ecbbcdc7e5ca:/$
# 按照以下命令,更新 Docker 镜像
sudo docker commit -m "update" ecbbcdc7e5ca docker_rk:latest
6. Dockerfile 参考
FROM ubuntu:22.04
RUN \
# use mirror sources
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse\n\
deb http://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse\n\
deb http://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse\n\
deb http://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse" \
> /etc/apt/sources.list \
# install packages
&& DEBIAN_FRONTEND=noninteractive apt-get update -y \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
bc binfmt-support bison bsdmainutils build-essential chrpath cmake cpio curl device-tree-compiler diffstat \
expat expect fdisk file flex gawk git iputils-ping libegl1-mesa libelf-dev libgmp-dev libgucharmap-2-90-dev \
liblz4-tool libmpc-dev libncurses-dev libsdl1.2-dev libssl-dev locales live-build mesa-common-dev net-tools \
patchelf python2 python2-dev python3 python-is-python3 python3-git python3-jinja2 python3-pexpect python3-pip \
python3-pyelftools python3-subunit qemu-user-static repo rsync ssh strace swig vim socat sudo texinfo time tree \
unzip wget \
# add user in docker
&& useradd -c 'rk user' -m -d /home/rk -s /bin/bash rk && usermod -a -G sudo rk \
&& sed -i -e '/\%sudo\tALL=(ALL:ALL) ALL/ c \%sudo ALL=(ALL) NOPASSWD: ALL' /etc/sudoers \
&& echo "docker image build complete"
# delete useless package and cache if need
#&& apt-get autoclean && apt-get autoremove && rm -rf /var/lib/apt/lists/*
7. 常见问题解答
7.1 获取镜像失败
报错如下:
error pulling image configuration: Get https:......read: connection reset by peer
当前⽹络⽆法访问 Docker 官⽹镜像仓库,可以通过配置 Docker 国内镜像仓库,解决⽆法访问的问题,可参考以下修改:
# 在 /etc/docker/daemon.json 添加以下内容
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
}
7.2 代码所有权转移问题
报错如下:
error.GitError: ...... rev-parse: fatal: detected dubious ownership in repository at
通常代码的所有权属于当前下载代码的 Host 主机⽤⼾,在 Docker 中编译时,因为 Docker 环境中的⽤⼾没有代码的所有权,所以会触发编译报错,可以通过以下命令修改所有仓库的转移权。当 Docker 内⽤⼾获得代码所有权时,相对的,Host 主机⽤⼾也会因为权限转移⽽丢失代码的权限。
git config --global --add safe.directory "*"