Docker容器相关

Docker 、Lxc介绍

docker是一个比较成熟好用的开源免费应用容器引擎,用于在一个集中的平台上创建、部署和工作应用程序。这使得主机的操作系统通过容器运行具有相同Linux内核的应用程序,而不是创建一个完整的虚拟机。使用docker容器,你不需要关心Ram和磁盘空间的分配。它能够自己处理需求。Docker容器将应用和其依赖环境全部打包到一个单一对象中,在不包含完整的操作系统的情况下就能运行普通应用,更加轻量级,可移植性更好。所以它成为了PaaS(比如Kubernates)平台的基石。

  • Docker高效且容易配置。
  • 技术可行性和提高生产力。
  • 可以创建更加安全的服务例如通过 secret inspect 和 secret create等。
  • 提供应用程序隔离,并且各个容器互相独立没有依赖。

在介绍LXD之前先介绍LXC,因为LXD可以视作LXC的升级版。LXD的管理命令和LXC的管理命令大多相同。LXC起源于cgroup和namespaces,使得进程之间相互隔离,即进程虚拟化。LXC有一些缺点,比如无法有效支持跨主机之间的容器迁移、管理复杂。而LXD很好地解决了这些问题。LXC/LXD和docker不同的地方在于LXC/LXD中包含完整的操作系统。

lxc是Linux Containers的缩写,用于通过单个Linux内核在受控主机上虚拟地运行多个 “Linux系统” 。内核的Cgroups管理绑定的lsc容器性能,为进程和网络空间提供功能,而不是创建一个完整的虚拟机,并为应用程序提供一个独立的环境。无论是 ip netns、lxd、docker daemon等还是其他自制的工具所创建的依赖linux内核namepspace底层机制的容器都应该算作广义上的lxc容器。

  • 它提供了内核名称空间,如IPC、mount、PID、network和user。
  • 它提供内核功能。
  • 控制组 (Control groups – Cgroups)
  • Seccomp概要文件 (Seccomp profiles )

Docker 和 LXD/LXC 区别

LXD/LXC是一个系统容器。Docker是一个应用程序容器,LXC不能跨机器上进行移植,而Docker可以跨机器甚至跨平台移植。lxc 是 Linux 内核容器虚拟化的一项技术,可以实现资源的隔离和控制,也就是对 Cgroup 和 Namespace 两个属性的控制。对于 docker 而言,它发展到现在不仅仅是容器的代名词了,不过它的基础技术是需要依赖内核的 CgroupNamespace 特性。docker 出现之初,便是采用了 lxc 技术作为 docker 底层,对容器虚拟化的控制。后来随着 docker 的发展,它自己封装了 libcontainer (golang 的库)来实现 Cgroup 和 Namespace 控制,从而消除了对 lxc 的依赖。

ParameterLXCDocker
开发者LXC was created by IBM, Virtuozzo, Google and Eric Biederman.Docker was created by Solomon Hykes in 2003.
数据检索LXC不支持处理后的数据检索。Docker支持数据检索。
可用性它是一个多用途的虚拟化解决方案。它是单一目的的解决方案。
平台LXC仅在Linux平台上支持。Docker的实现依赖于平台。
虚拟化LXC为我们提供了完整的系统虚拟化 。Docker提供了应用虚拟化。
云支持不需要云存储,因为是Linux提供了这些特性。云存储的需求是一个相当大的生态系统所必需的。
流行性由于一些限制,LXC在开发人员中并不是很流行。Docker因容器而流行,它将容器提升到了一个新的层次。

  • cgroup:Cgroup 是 Control group 的简称,是 Linux 内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用。对不同资源的具体管理是由各个子系统分工完成的。

    子系统作用
    devices设备权限控制
    cpuset分配指定的CPU和内存节点
    CPU控制CPU使用率
    cpuacct统计CPU使用情况
    memory限制内存的使用上限
    freezer暂停Cgroup 中的进程
    net_cls配合流控限制网络带宽
    net_prio设置进程的网络流量优先级
    perf_event允许 Perf 工具基于 Cgroup 分组做性能检测
    huge_tlb限制 HugeTLB 的使用
  • Namespace:Namespace 是将内核的全局资源做封装,使得每个namespace 都有一份独立的资源,因此不同的进程在各自的namespace内对同一种资源的使用互不干扰。

    Namespace作用
    IPC隔离 System V IPC 和 POSIX 消息队列
    Network隔离网络资源
    Mount隔离文件系统挂载点
    PID隔离进程ID
    UTS隔离主机名和域名
    User隔离用户和用户组

常见问题

  • Container内不需要OS,为何需要OS的基础镜像?

  • Vscode 插件无法查看镜像

    默认情况下,docker 命令会使用 Unix socket (opens new window)与 Docker 引擎通讯。 而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑, 一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

    # 建立 docker 组:
    sudo groupadd docker
    # 将当前用户加入 docker 组:
    sudo usermod -aG docker $USER
    
  • Docker网络管理 (导出端口,多容器间通信 等问题分析)

  • 配置代理

    国内特殊环境,pull 镜像可能比较麻烦,换镜像源。

    nano /etc/docker/daemon.json
    # 写入以下内容
    {
      "registry-mirrors": [
        "https://hub-mirror.c.163.com",
        "https://mirror.baidubce.com"
      ]
    }
    # 之后重启docker
    sudo service docker restart
    
  • 自定义网桥

    可以用 docker port 容器id 查看容器导出接口端口port,或者直接 docker ps

    由于之前手贱,ip link del docker0 网桥导致后面的容器无法导出端口,使用此法加回来

    ip link add docker0(名字与下面 *daemon.json* 使用相同的名字)
    sudo ip addr add 192.168.5.1/24 dev docker0
    sudo ip link set dev docker0 up
    
    nano /etc/docker/daemon.json
    # 添加以下内容
    {
    	"bridge": "docker0",
    }
    
    # 之后重启docker
    sudo service docker restart
    

常用命令

Docker build options

Docker run options

命令功能
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]默认地址是 Docker Hub(docker.io)。 这里的仓库名是两段式名称,即 <用户名>/<软件名>。 对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
docker container ls -a查看全部容器 删除rm
docker docker image ls -a查看全部镜像 删除镜像用rm
docker build -t nginx:v1 .编译镜像 -t 设定容器名及tag 后面的 . 设定的是上下文的路径
docker build -t koa-demo:0.1 . -f ./koa-docker/Dockerfile可以使用 dockerfile 取消跟踪拷贝文件 注意默认dockfile是在设定上下文目录中寻找,copy的文件只能是上下文目录及其子目录 -f 可以指定dockefile :
docker image prune删除悬浮镜像
docker system df/ prune / events显示各项数据磁盘占用 清除无用数据 查看docker server实时事件
docker history image名查看镜像操作历史记录
docker run –name webserver -d -p 1080:80 nginx:v1使用镜像生成新容器并直接运行(命名为webserver -p 物理机1080代理容器80端口 -d deatch )
docker run –rm -it \ -v /var/sflowtrend-pro:/var/local/sflowtrend-pro \ koa-demo:0.2 bash-i绑定终端输入 -t生成虚拟终端tty -i -t 等价-it –rm:这个参数是说容器退出后随之将其删除 -d 后台运行 -v 将主机的/var/sflowtrend-pro目录挂载到/var/local/sflowtrend-pro中
docker container start/stop laughing_jennings/或者容器id启动/中止 容器 laughing_jennings
docker container logs 容器名或id查看容器运行输出
docker diff 容器名或id查看容器修改文件
docker attach 243c进入容器执行操作 使用 attach 进入容器 当这个终端停止或exit时容器也会停止
docker exec -i 69d1 bash使用exec则无影响,仅仅是执行bash并定向到当前stdin 其他参数使用docker exec -h 查看
docker commit \ –author “Tao Wang twang2218@gmail.com” \ –message “修改了默认网页” \ webserver \ nginx:v2提交容器内改变编译生成镜像 commit生成的镜像为黑箱镜像还是推荐用dockerfile做是维护用的镜像 dockerfile使用
docker export 7691a814370e > ubuntu.tar导出容器的快照到本地归档文件
cat ubuntu.tar | docker import - test/ubuntu:v1.0 或者指定url下载并导入 docker import http://example.com/exampleimage.tgz example/imagerepo将容器归档文件导入为镜像 用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
docker save alpine -o filename docker save alpine | gzip > alpine-latest.tar.gz docker load -i alpine-latest.tar.gzsave load为镜像的保存与导入,现在已经不推荐,镜像迁移应该直接使用 Docker Registry,无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以)
docker ps -aq显示docker所有容器 (-a 为全部否则默认只有运行容器 -q只显示容器id)
docker top 容器id查看容器内进程
docker inspect –format ‘{{ .NetworkSettings.IPAddress }}’ 容器id查看容器ip
docker inspect –format=’{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}’ $(docker ps -aq)查看全部容器ip

如果我们结合这两个命令以及 ssh 甚至 pv 的话,利用 Linux 强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能:

docker save <镜像名> |bzip2 |pv |ssh <用户名>@<主机名> 'cat |docker load'

其实有很多插件可以方便快捷操作,例如vscode中的docker插件,这里推荐一下。