白首齐眉网

docker

docker

文章目录

  • Docker 仓库管理
    • docker连接远程仓库
  • 容器命令
    • 运行模式
      • attached模式
      • detached模式
      • detached模式转换为attached模式
    • 交互模式
    • 文件复制
    • 镜像导入导出
      • 导出
        • 镜像导出
      • 容器导出
      • commit 镜像
      • 导入
    • 停用全部运行中的容器
    • docker删除所有容器
    • 停用并删除容器
    • 使用数据卷
      • 匿名挂载和具名挂载
    • 配置环境
    • 查看容器信息
    • runtime
    • docker内存限额:
    • CPU限制:
  • DockerFile
    • 常用命令
    • 构建ROS镜像实例
    • Dockerfile 构建镜像
    • 查看镜像是如何通过DockerFile构建的
  • Docker网络
  • docker-compose
    • 实例
    • docker-compose启用GPU访问
      • 旧版
    • 新版
  • 进阶问题
    • docker 显示
      • 为什么需要DRI
    • Docker使用GPU
      • 手动配置镜像
    • 它是如何工作的?
  • 权限问题
    • No protocol specified问题
    • 把用户添加进Docker用户组

Docker 仓库管理

docker连接远程仓库

$ docker login [OPTIONS] [SERVER]# docker login -u Username -p Password  [SERVER]

Options:

  • -p, --password string Password
    –password-stdin Take the password from stdin
  • -u, --username string Username
  • [SERVER]是服务器地址

容器命令

$ docker container run 参数 镜像名称:tag 执行的命令

参数

  • -p :端口映射,第一个port是本机的端口,第二个port是Docker容器的端口
  • -i:保持和docker 容器内的交互,启动容器时,运行的命令结束后,容器依然存活,没有退出(默认是会退出,即停止的)
  • -t:为容器的标准输入虚拟一个tty
  • -d:后台运行容器
  • --name string:给容器起一个自定义名称
  • --rm:容器在启动后,执行完成命令或程序后就销毁

运行模式

attached模式

前台运行

detached模式

后台运行

开启方法:参数-d或者--detach

detached模式转换为attached模式

docker attach 

交互模式

直接进入交互模式

docker exec -it sh 

文件复制

docker cp 容器ID:容器内文件路径 目的主机路径

镜像导入导出

导出

镜像导出

$ docker save [OPTIONS] IMAGE [IMAGE...]# docker save -o image.tar my/image

OPTIONS说明:

  • -o:输出到文件

容器导出

$ docker export CONTAINER >name.tar

将容器以tar包的形式导出到标准输出,然后重定向到目标文件name.tar

commit 镜像

将容器转化为镜像

# 提交容器作为一个新的副本,命令与git类似docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]#eg: docker commit -m="提交的信息" -a="作者" 容器Id 目标镜像名:[Tag]

Options:

  • -a, --author string Author (e.g., “John Hannibal Smith”)
  • -c, --change list Apply Dockerfile instruction to the created image
  • -m, --message string Commit message
  • -p, --pause Pause container during commit (default true)

CONTAINER为容器ID或名字

[REPOSITORY[:TAG]]为镜像

导入

$ docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

导入一个本地的tar包作为镜像

$ docker load [OPTIONS]# docker load < image.tar

OPTIONS说明:

  • –input,-i:指定导入的文件,带起STDIN
  • –quiet,-q:精简输出信息

停用全部运行中的容器

$ docker stop $(docker ps -q)

docker删除所有容器

$ docker rm $(docker ps -aq)

停用并删除容器

$ docker stop $(docker ps -q) && docker rm $(docker ps -aq)

使用数据卷

方式一 :直接使用命令来挂载 -v (volume) 指定路径挂载

docker run  -v 主机目录:容器内目录

匿名挂载和具名挂载

匿名挂载就是不写主机目录,随机指定主机目录

docker run  -v 容器内目录

具名挂载就是给卷起一个卷名(不是主机目录)

docker run -v 卷名:容器内目录

通过具名挂载可以用

docker volume inspect 卷名

来查看卷的信息

在容器内目录后加(:rw)或(:ro)可以定义卷的权限readwrite read-only

docker run -v 卷名:容器内目录:rw

配置环境

docker run -e 环境变量=值

查看容器信息

docker inspect 容器ID

runtime

容器创建需要:1、内核 2、runtime 3、管理工具

runtime 是容器真正运行的地方。runtime 需要跟操作系统 kernel 紧密协作,为容器提供运行环境,lxc、runc 和 rkt 是目前主流的三种容器 runtime。MANO使用的是runc 通过docker info可以查看。

runc 的管理工具是 docker engine。docker engine 包含后台 deamon 和 cli 两个部分。我们通常提到Docker,一般就是指的 docker engine。

docker内存限额:

docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M

  1. -m 或 --memory:设置内存的使用限额,例如 100M, 2G。

  2. –memory-swap:设置 内存+swap 的使用限额。

  3. 默认情况下,上面两组参数为 -1,即对容器内存和 swap 的使用没有限制

  4. –vm 1:启动 1 个内存工作线程

  5. –vm-bytes 280M:每个线程分配 280M 内存。

progrium/stress为镜像名称,如果–memory-swap不写,默认是memory的两倍

CPU限制:

Docker 可以通过 -c 或 --cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。

与内存限额不同,通过 -c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。

DockerFile

常用命令

FROM  #基础镜镜像,一切从这里开始构建MAINTAINER  #镜像是谁写的,姓名+邮箱RUN   #镜像构建的时候需要运行的命令ADD 本机文件名 容器内目录  #构建镜像时添加的文件,Copy文件,自动解压COPY #类似ADD,将我们文件拷贝到镜像中WORKDIR #镜像的工作目录VOLUME ["/卷1",...] #通过VOLUME指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。EXPOSE #暴露端口配置CMD   #容器启动时默认运行的命令,命令行中run命令指定了其他命令则会替换CMD,如果定义多个CMD只有最后一个会被执行ENTRYPOINT #与CMD类似,但是命令行中run命令不会被替换ENTRYPOINT,而是追加,可以与CMD联合使用,ENTRYPOINT设置执行的命令,CMD传递参数ONBUILD #当构建一个被继承DockerFile 这个时候就会运行ONBUILD的指令。触发指令。#设置子镜像的触发操作。构建镜像时,Docker的镜像构建器会将所有的ONBUILD指令指定的命令保存到镜像的元数据中,这些命令在当前镜像构建过程中不会执行。只有在新的镜像使用FROM指令指定父镜像为此镜像时,便会触发执行。ENV #构建的时候设置环境变量!ARG #构建的时候设置Dockerfile变量,不会带到镜像里!可以在构建镜像时设置 --build-arg ARG=..
  • CMD设置的命令,可以在 docker container run时传入其它命令,覆盖掉 CMD的命令,但是ENTRYPOINT所设置的命令时一定会被执行的。
  • ENTRYPOINTCMD可以联合使用, ENTRYPOINT设置执行的命令,CMD传递参数。

构建ROS镜像实例

FROM ros:humble# 将sh改为bashRUN rm /bin/sh && ln -s /bin/bash /bin/sh# RVIZ的使用及其他图形化应用的使用ENV NVIDIA_VISIBLE_DEVICES ${ NVIDIA_VISIBLE_DEVICES:-all}ENV NVIDIA_DRIVER_CAPABILITIES ${ NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphicsENV DEBIAN_FRONTEND noninteractive# 换源RUN cp /etc/apt/sources.list /etc/apt/sources.list.bak && \echo -e "deb https://repo.huaweicloud.com/ubuntu/ jammy main restricted universe multiverse\n\deb https://repo.huaweicloud.com/ubuntu/ jammy-updates main restricted universe multiverse\n\deb https://repo.huaweicloud.com/ubuntu/ jammy-backports main restricted universe multiverse\n\deb https://repo.huaweicloud.com/ubuntu/ jammy-security main restricted universe multiverse\n\deb https://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse\n\deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse\n\deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse\n\deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse" \>/etc/apt/sources.list && \echo "deb [arch=$(dpkg --print-architecture)] http://repo.huaweicloud.com/ros2/ubuntu/ `lsb_release -cs` maindeb [arch=$(dpkg --print-architecture)] http://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu/ `lsb_release -cs` main" \>/etc/apt/sources.list.d/ros2-latest.list # 安装RUN apt update && apt install apt-utils && echo "source /opt/ros/humble/setup.bash" >>/root/.bashrcRUN apt install -y ros-${ ROS_DISTRO}-xacro ros-${ ROS_DISTRO}-rviz2 ros-${ ROS_DISTRO}-navigation2 ros-${ ROS_DISTRO}-nav2-bringup ros-${ ROS_DISTRO}-turtlebot3*

NVIDIA_VISIBLE_DEVICES表示查看当前电脑或服务器上有的GPU,-all则是将宿主机上所有的GPU的环境变量设置到image中,使得image能够使用宿主机上的GPU

使用docker制作镜像过程中,在 apt-get 安装命令时,出现错误:

debconf: unable to initialize frontend: Dialogdebconf: (TERM is not set, so the dialog frontend is not usable.)debconf: falling back to frontend: Readlinedebconf: unable to initialize frontend: Readlinedebconf: (This frontend requires a controlling tty.)debconf: falling back to frontend: Teletypedpkg-preconfigure: unable to re-open stdin: 

是因为在使用apt-get安装依赖时,可能会有对话框,制作镜像时如果不选择会导致失败。

解决方案:在Dockerfile中增加一句:ENV DEBIAN_FRONTEND noninteractive

Dockerfile 构建镜像

docker image build [OPTIONS] PATH |URL| 
  • -f dockerfilename
  • -t listor --tag list
    Name and optionally a tag in the ‘name:tag’ format

查看镜像是如何通过DockerFile构建的

docker history 镜像

Docker网络

docker run 创建Docker容器时,可以用--net=选项指定容器的网络模式:

  1. host模式:
    默认docker容器运行会分配独立的networknamspace隔离子系统,基于host模式,容器将不会获得一个独立的networknamespace,而是和宿主机共用一个network namespace,容器将不会虚拟出自己的网卡等信息,而是使用宿主机的IP和端口。

  2. container模式:
    其实container模式,其实就是容器之间共享一个networknamespace,而不是和宿主机共享,也就是说新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享网络环境,同样,两个容器除了网络方面相同之外,其他的包括文件系统,进程列表等还是隔离的。

  3. None模式:
    None模式与其他模式都不同,这种模式docker容器会拥有自己独立的networknamespace,但是并不会为docker容器进行任何网络配置,也就是说,该docker容器没有网络信息,需要手动自定义等,我们可以借助pipwork工具为docker容器指定IP信息等;

  4. Bridge桥接模式:
    bridge模式是docker默认的网络模式,该模式宿主机会为每一个容器自动分配一个networknamespace,默认会将docker容器连接到一个虚拟网桥交换机docker0上。

在这里插入图片描述

#我们发现这个容器带来网卡,都是一对对的# evth-pair 就是一 对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连#正因为有这个特性,evth-pair 充当一个桥梁, 连接各种虚拟网络设备的# openstac, Docker容器之间的连接,OVS的连接, 都是使用evth-pair 技术
  • Docker Bridge创建创建过程:
    1. 首先宿主机上创建一对虚拟网卡veth pair设备,veth设备总是成对出现的,形成一个通信通道,数据传输就是基于这个链路的,veth设备常用来连接两个网络设备
    2. Docker将veth pair设备的一端放在容器中,并命名为eth0,然后将另一端加入docker0网桥中,可以通过brctl show命令查看
    3. 从docker0网卡中分配一个IP到给容器使用,并设置docker0的IP地址为容器默认网关
    4. 此时容器IP与宿主机是可以通信的,宿主机也可以访问容器中的ip地址,在bridge模式下,连接同一网桥的容器之间可以相互通信,同时容器可以访问外网,但是其他物理机不能访问docker容器IP:需要通过NAT将容器的IP的port映射为宿主机的IP和port;

docker-compose

docker-compose是Docker官方的开源项目,不在docker中,要另外安装。

作用:批量容器编排

步骤:

  1. Dockerfile定义你的环境
  2. 定义Services需要的docker-compose.yaml
  3. Run docker-compose up启动项目

实例

version: '2.3'services:  nav2:  	# 指定当前服务(容器)依赖的服务  	depend_on:  	  - dp    container_name: nav2    restart: always    # 指定通过Dockerfile去构建镜像    build: .    # 指定容器运行的镜像    image: long/nav2:humble    # 覆盖容器启动后默认执行的命令    command: lxterminal    # 覆盖容器默认的entrypoint    entrypoint: ./setup.bash    runtime: nvidia    # 指定设备映射列表    devices:        - "/dev/snd:/dev/snd"        - "/dev/dri:/dev/dri"    privileged: true    stdin_open: true    tty: true    # 默认工作目录    working_dir: /root/nav2_ws    # 添加环境变量    environment:        - DISPLAY=unix$DISPLAY        - QT_X11_NO_MITSHM=1    # 指定挂载数据卷    volumes: # 数据卷名称(卷标)或宿主机路径:容器中的路径:权限      - /tmp/.X11-unix:/tmp/.X11-unix:rw      - /home/long/nav2_ws:/root/nav2_ws:rw      - volume1:~/cache    networks:      - app_net    # 设置网络连接模式      network_mode: host    # 对外暴露的端口,格式 为 宿主:容器(HOST:CONTAINER)    ports:      - "8000:8000"      - target: 80 #容器内的端口        published: 8080 #物理主机的端口        protocol: tcp #端口协议(tcp或udp)        mode: host #host和ingress两种模式,host用于在每个节点上发布主机端口,ingress用于被负载平衡的swarm模式端口    # 暴露端口,但不映射到宿主机    expose:      - "8000"    entrypoint: ["echo 'hello'"]    # 链接到另一个服务的容器    links:      -     # 链接到docker-compose.yml外部的容器    external_links:       - # 配置容器连接的网络变量networks:  #指定网络的名称,默认会创建bridge桥接网络  app_net:    driver: custom-driver-1# 指定卷标(数据卷变量)volues:  volume1:

docker-compose启用GPU访问

旧版

这通过使用服务属性runtime的使用,以提供对服务容器的GPU访问。但是,这不允许控制GPU设备的特定属性。

version: '2.3'services:  test:    image: nvidia/cuda:10.2-base    command: nvidia-smi    runtime: nvidia

新版

点我

进阶问题

docker 显示

/dev/snd是声卡系统

/dev/dri是 gazebo仿真

为什么需要DRI

http://www-x-wowotech-x-net.img.abc188.com/content/uploadfile/201512/5b56a76a97467a71495cd5b764b3ed4720151217141926.gif

在GUI环境中,一个Application想要将自身的UI界面呈现给用户,需要2个步骤:

  1. 根据实际情况,将UI绘制出来,以一定的格式,保存在buffer中。该过程就是常说的“Rendering”渲染。实际上就是生成图像数据的过程。

  2. 将保存在buffer中的UI数据,显示在display device上。该过程一般称作“送显”。

    在操作系统中,Application不应该直接访问硬件,通常的软件框架是(从上到下):Application<---->Service<---->Driver<---->Hardware。这样考虑的原因主要有二:安全性和共享硬件资源(例如显示设备只有一个,却有多个应用想要显示)

Linux图形子系统包括如下的软件的软件模块:

  1. 3D-game engine、Applications和Toolkits,应用软件,其中3D-game engine是3D application的一个特例。

  2. Display Server

    图片给出了两个display server:Wayland compositor和X-Server(X.Org)。X-Server是linux系统在PC时代使用比较广泛的display server,而Wayland compositor则是新设计的,计划在移动时代取代X-Server的一个新的display server。

  3. libX/libXCB和libwayland-client

    display server提供给Application(或者GUI Toolkits)的、访问server所提供功能的API。libX/libXCB对应X-server,libwayland-client对已Wayland compositor。

  4. libGL

    libGL是openGL接口的实现,3D application(如这里的3D-game engine)可以直接调用libGL进行3D渲染。

    libGL可以是各种不同类型的openGL实现,如openGL(for PC场景)、openGL|ES(for嵌入式场景)、openVG(for Flash、SVG矢量图)。

    libGL的实现,既可以是基于软件的,也可以是基于硬件的。其中Mesa 3D是OpenGL的一个开源本的实现,支持3D硬件加速。

  5. libDRM和kernel DRM

    DRI(Direct Render Infrastructure)的kernel实现,及其library。X-server或者Mesa 3D,可以通过DRI的接口,直接访问底层的图形设备(如GPU等)。

  6. KMS(Kernel Mode Set)

    一个用于控制显示设备属性的内核driver,如显示分辨率等。直接由X-server控制。

Docker使用GPU

Docker 容器共享您主机的内核,但带有自己的操作系统和软件包。这意味着它们缺少用于与 GPU 交互的 NVIDIA 驱动程序。默认情况下,Docker 甚至不会向容器添加 GPU,因此docker run根本看不到您的硬件。

概括地说,让 GPU 工作是一个两步过程:在映像中安装驱动程序,然后指示 Docker 在运行时将 GPU 设备添加到容器中。

在继续进行 Docker 配置之前,请确保您的主机上的 NVIDIA 驱动程序正常工作。您应该能够成功运行nvidia-smi并看到您的 GPU 名称、驱动程序版本和 CUDA 版本。

要将 GPU 与 Docker 结合使用,首先要在主机安装NVIDIA Container Toolkit。这集成到 Docker 引擎中以自动配置您的容器以支持 GPU。

docker run -it --gpus all nvidia/cuda:11.4.0-base-ubuntu20.04 nvidia-smi

手动配置镜像

注意 Dockerfile 末尾的环境变量——这些定义了使用你的镜像的容器如何与 NVIDIA Container Runtime 集成:

ENV NVIDIA_VISIBLE_DEVICES allENV NVIDIA_DRIVER_CAPABILITIES compute,utility

一旦安装了 CUDA 并设置了环境变量,您的镜像应该会检测到您的 GPU。这使您可以更好地控制镜像的内容,但随着新 CUDA 版本的发布,您可能需要调整。

它是如何工作的?

NVIDIA Container Toolkit 是一个包的集合,它们将容器运行时(如 Docker)与主机上 NVIDIA 驱动程序的接口包装在一起。该libnvidia-container库负责提供 API 和 CLI,通过运行时包装器自动将系统的 GPU 提供给容器。

该nvidia-container-toolkit组件实现了一个容器运行时prestart钩子。这意味着它会在新容器即将启动时收到通知。它查看您要附加并调用libnvidia-container以处理容器创建的 GPU 。

挂钩由nvidia-container-runtime启用。这会包装您的“真实”容器运行时,例如 containerd 或 runc,以确保prestart运行NVIDIA挂钩。在钩子执行后,您现有的运行时会继续容器启动过程。安装容器工具包后,您将看到在 Docker 守护程序配置文件中选择了 NVIDIA 运行时。

权限问题

No protocol specified问题

这是由于X11服务默认只允许『来自本地的用户』启动的图形程序将图形显示在当前屏幕上。解决的办法很简单,允许所有用户访问X11服务即可。这个事情可以用xhost命令完成

在宿主机中运行

$ sudo apt-get install x11-xserver-utils$ xhost +

参数+表示允许任意来源的用户,如果要指定docker的话,也可以运行以下命令:

$ xhost +local:docker

把用户添加进Docker用户组

使用docker的过程中,很多情况下都需要root权限才可以;为了避免多次使用sudo命令,故在此将当前用户添加到docker组;

# 添加docker用户组,一般已存在,不需要执行sudo groupadd docker# 将登陆用户加入到docker用户组中sudo gpasswd -a $USER dockersudo usermod -aG docker $USER#重启服务sudo service docker restart# 更新用户组newgrp docker# 测试docker命令是否可以使用sudo正常使用docker version

未经允许不得转载:白首齐眉网 » docker