0%

Docker使用大全

基本

安装

以Ubuntu为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo docker run hello-world

概念

image

Docker的镜像可以理解是一个只读的静态模板,类似于我们在装系统的时候用到的.iso文件。

列出所有的镜像:docker images

container

container则相对而言是一个动态的instance,可以理解为我们装好了系统之后的某一台计算机,可以开机,关机,重启等等,也可以被格式化(删除)

列出所有的容器:docker ps -a

Repository

我们可以把构建后的镜像上传到服务器,从而可以在任何地方使用到这个镜像。一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。
最常使用的Registry公开服务是官方的Docker Hub ,这也是默认的Registry,并拥有大量的高质量的官方镜像。

登录Registry:docker login xxx

基本的使用

镜像

  • 拉取镜像:docker pull ubuntu
  • 推送镜像:docker push username/repository:tag

容器

  • 运行:

    1
    2
    3
    4
    5
    6
    docker run  -d --name "test" -it ubuntu bash
    #-d 后台运行
    docker exec -it test bash
    #-i 以交互模式运行容器
    #-t 为容器重新分配一个伪输入终端
    #在容器内执行/bin/bash命令
  • 停止:

    1
    2
    3
    docker stop test
    #删除
    #docker rm test
  • 恢复(物理机关机重启):

    1
    docker start test  
  • 提交当前container为新镜像:

    1
    docker commit test  dev:cpp 

高级用法

定制镜像

Dockerfile

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,这个脚本就是 Dockerfile。Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM debian:stretch
#FROM 就是指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
RUN set -x; buildDeps='gcc libc6-dev make wget' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
#同一目的的所有命令应该归到同一层
#镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。

构建镜像

Dockerfile 文件所在目录执行

1
2
docker build -t redes:v3 . 
# . 是在指定上下文的目录,COPY需要用到该设置

Dockerfile指令

Dockerfile 功能很强大,它提供了十多个指令:

  • COPY <源路径>... <目标路径>:指令将从构建上下文目录中 <源路径> 的文件复制到新的一层的镜像内的 <目标路径> 位置
  • ENV <key1>=<value1> <key2>=<value2>...:设置环境变量
  • CMD ["nginx", "-g", "daemon off;"]CMD 指令就是用于指定默认的容器主进程的启动命令的。容器内没有后台服务的概念,我们应该直接执行可执行文件,并且要求以前台形式运行。

其他命令详见Dockerfile 指令详解 - Docker —— 从入门到实践 (gitbook.io)

VSCode

noroot运行

vscode 使用docker必须设置rootless运行

1
dockerd-rootless-setuptool.sh install

使用

  • 安装Remote - Containers拓展

  • 在远程服务器上启动Container

  • VSCode连接远程服务器

  • 选择对应Container->Attach

  • 打开文件夹

高级配置

网络

网络模式

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

除了默认的bridge模式,docker还提供三种网络模式

网络模式 配置 说明
bridge模式 –net=bridge 默认为该模式)此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥。docker网络模式-bridge
host模式 –net=host 容器和宿主机共享网络空间。docker网络模式-host
container模式 –net=container:NAME_or_ID 容器和另外一个容器共享网络空间。docker网络模式container
none模式 –net=none 该模式关闭了容器的网络功能。

端口转发

默认的Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p-P 参数来启用,访问容器的时候就通过 [宿主机IP]:[容器端口] 访问容器。

1
2
docker run -p 8000:80 -it ubuntu /bin/bash
#将容器的80端口映射到宿主机的8000端口上

文件

Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定,冒号:前面的目录是宿主机目录,后面的目录是容器内目录。这样在容器启动后,容器内会自动创建/project的目录。

1
-v /src/myproject:/project

其他配置

  • 设置工作目录:-w /project
  • 退出时清除自动清理容器内部的文件系统:-rm

在Docker中使用GPU

安装nvidia-docker2

需要提前在宿主机上安装显卡驱动

1
2
3
4
5
6
7
8
#设置NVIDIA Container Toolkit
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
&& curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
#安装nvidia-docker2
sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker

使用

添加--gpus <device id> 参数,--gpus all使用所有的GPU。

1
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

GUI程序的运行

X11

最简单的方法是暴露宿主机的xhost,这样容器就可以通过对X11的unix套接字的读写间接渲染程序界面。

1
2
3
4
5
6
7
8
9
#调整Xserver权限
xhost +local:root
#docker 设置
docker run -it \
--env="DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
osrf/ros:indigo-desktop-full \
rqt

x11docker

x11docker允许在Linux容器中运行图形化桌面应用程序。

  • 安装:

    1
    2
    curl -fsSL https://raw.githubusercontent.com/mviereck/x11docker/master/x11docker | sudo bash -s -- --update
    docker pull x11docker/xserver
  • 使用:

    1
    x11docker IMAGENAME [COMMAND] 

    可选参数:

    • --desktop提供桌面环境。
    • --gpu用于硬件加速

Install Docker Engine | Docker Documentation

前言 - Docker —— 从入门到实践 (gitbook.io)

docker四种网络模式 - SegmentFault 思否

NVIDIA/nvidia-docker: Build and run Docker containers leveraging NVIDIA GPUs (github.com)

docker/Tutorials/GUI - ROS Wiki

mviereck/x11docker: Run GUI applications and desktops in docker and podman containers. Focus on security. (github.com)