docker 介绍

  |  

全部的 K8S学习笔记总目录,请点击查看。

认识docker

Docker 公司位于旧金山,原名dotCloud,底层利用了Linux容器技术(LXC)(在操作系统中实现资源隔离与限制)。为了方便创建和管理这些容器,dotCloud 开发了一套内部工具,之后被命名为“Docker”。Docker就是这样诞生的。

Hypervisor: 一种运行在基础物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享硬件 。常见的VMware的 Workstation 、ESXi、微软的Hyper-V或者思杰的XenServer。

Container Runtime:通过Linux内核虚拟化能力管理多个容器,多个容器共享一套操作系统内核。因此摘掉了内核占用的空间及运行所需要的耗时,使得容器极其轻量与快速。Docker是其中最知名的一种容器Container Runtime,其他的还有 CoreOS 容器 Rkt ,Podman。

docker-different

docker能做什么呢? 它主要基于轻量的特性,解决软件交付过程中的环境依赖

  • 可以把应用程序代码及运行依赖环境打包成镜像,作为交付介质,在各环境部署
  • 可以将镜像(image)启动成为容器(container),并且提供多容器的生命周期进行管理(启、停、删)
  • container容器之间相互隔离,且每个容器可以设置资源限额
  • 提供轻量级虚拟化功能,容器就是在宿主机中的一个个的虚拟的空间,彼此相互隔离,完全独立

docker的发展史

13年成立,15年开始,迎来了飞速发展。

Docker 1.8 之前,使用LXC,Docker在上层做了封装, 把LXC复杂的容器创建与使用方式简化为自己的一套命令体系。

之后,为了实现跨平台等复杂的场景,Docker抽出了libcontainer项目,把对namespace、cgroup的操作封装在libcontainer项目里,支持不同的平台类型。

2015年6月,Docker牵头成立了 OCI(Open Container Initiative开放容器计划)组织,这个组织的目的是建立起一个围绕容器的通用标准 。 容器格式标准是一种不受上层结构绑定的协议,即不限于某种特定操作系统、硬件、CPU架构、公有云等 , 允许任何人在遵循该标准的情况下开发应用容器技术,这使得容器技术有了一个更广阔的发展空间。

OCI成立后,libcontainer 交给OCI组织来维护,但是libcontainer中只包含了与kernel交互的库,因此基于libcontainer项目,后面又加入了一个CLI工具,并且项目改名为runC (https://github.com/opencontainers/runc ), 目前runC已经成为一个功能强大的runtime工具。

Docker也做了架构调整。将容器运行时相关的程序从docker daemon剥离出来,形成了containerd。containerd向上为Docker Daemon提供了gRPC接口,使得Docker Daemon屏蔽下面的结构变化,确保原有接口向下兼容。向下通过containerd-shim结合runC,使得引擎可以独立升级,避免之前Docker Daemon升级会导致所有容器不可用的问题。

containerd

  • runC(libcontainer)是符合OCI标准的一个实现,与底层系统交互
  • containerd是实现了OCI之上的容器的高级功能,比如镜像管理、容器执行的调用等
  • Dockerd目前是最上层与CLI交互的进程,接收cli的请求并与containerd协作

docker总结

  1. 为了提供一种更加轻量的虚拟化技术,docker出现了
  2. 借助于docker容器的轻、快等特性,解决了软件交付过程中的环境依赖问题,使得docker得以快速发展
  3. Docker是一种CS架构的软件产品,可以把代码及依赖打包成镜像,作为交付介质,并且把镜像启动成为容器,提供容器生命周期的管理
  4. docker-ce,每季度发布stable版本。18.06,18.09,19.03
  5. 发展至今,docker已经通过制定OCI标准对最初的项目做了拆分,其中runC和containerd是docker的核心项目,理解docker整个请求的流程,对我们深入理解docker有很大的帮助

docker安装

docker安装查看这篇文章 docker安装(Centos8版本)

核心要素

docker中的三大核心要素:镜像(Image)、容器(Container)、仓库(Registry)

  1. 镜像(Image):打包了业务代码及运行环境的包,是静态的文件,不能直接对外提供服务。
  2. 容器(Container): 镜像的运行时,可以对外提供服务。
  3. 仓库(Registry): 存放镜像的地方
    • 公有仓库,Docker Hub,阿里仓库,网易仓库…
    • 私有仓库,企业内部搭建
      • Docker Registry,Docker官方提供的镜像仓库存储服务
      • Harbor, 是Docker Registry的更高级封装,它除了提供友好的Web UI界面,角色和用户权限管理,用户操作审计等功能
    • 镜像访问地址形式 registry.devops.com/demo/hello:latest,若没有前面的url地址,则默认寻找Docker Hub中的镜像,若没有tag标签,则使用latest作为标签。 比如,docker pull nginx,会被解析成docker.io/library/nginx:latest
    • 公有的仓库中,一般存在这么几类镜像
      • 操作系统基础镜像(centos,ubuntu,suse,alpine)
      • 中间件(nginx,redis,mysql,tomcat)
      • 语言编译环境(python,java,golang)
      • 业务镜像(django-demo…)

容器和仓库不会直接交互,都是以镜像为载体来操作。

docker基本命令

docker-command

  1. 查看镜像列表

    根据以下指标确定唯一镜像

    • image_id
    • repository:tag
    1
    2
    3
    $ docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    nginx alpine 377c0837328f 2 weeks ago 19.7MB
  2. 如何获取镜像

    • 从远程仓库拉取

      1
      2
      3
      # 推荐alpine
      $ docker pull nginx:alpine
      $ docker images
    • 使用tag命令

      1
      2
      $ docker tag nginx:alpine 172.21.51.143:5000/nginx:alpine
      $ docker images
    • 本地构建(通过Dockerfile)

      1
      $ docker build . -t my-nginx:ubuntu -f Dockerfile
  3. 如何通过镜像启动容器

    1
    $ docker run --name my-nginx-alpine -d nginx:alpine
  4. 如何知道容器内部运行了什么程序?

    1
    2
    3
    # 进入容器内部,分配一个tty终端
    $ docker exec -ti my-nginx-alpine /bin/sh
    # ps aux
  5. docker怎么知道容器启动后该执行什么命令?

    通过docker build来模拟构建一个nginx的镜像,

    • 创建Dockerfile

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      # 告诉docker使用哪个基础镜像作为模板,后续命令都以这个镜像为基础 
      FROM ubuntu

      # 替换源
      RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

      # RUN命令会在上面指定的镜像里执行命令
      RUN apt-get update && apt install -y nginx

      #告诉docker,启动容器时执行如下命令
      CMD ["/usr/sbin/nginx", "-g","daemon off;"]
    • 构建本地镜像

      1
      $ docker build . -t my-nginx:ubuntu -f Dockerfile
    • 使用新镜像启动容器

      1
      $ docker run --name my-nginx-ubuntu -d my-nginx:ubuntu
    • 进入容器查看进程

      1
      2
      $ docker exec -ti my-nginx-ubuntu /bin/sh
      # ps aux
  6. 如何访问容器内服务

    1
    2
    3
    4
    # 进入容器内部
    $ docker exec -ti my-nginx-alpine /bin/sh
    # ps aux|grep nginx
    # curl localhost:80
  7. 宿主机中如何访问容器服务

    1
    2
    3
    4
    # 删掉旧服务,重新启动
    $ docker rm -f my-nginx-alpine
    $ docker run --name my-nginx-alpine -d -p 8080:80 nginx:alpine
    $ curl 172.21.51.143:8080
  8. docker client如何与daemon通信

    1
    2
    # /var/run/docker.sock
    $ docker run --name portainer -d -p 9001:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
  9. 导出镜像到文件中

    1
    $ docker save -o nginx-alpine.tar nginx:alpine
  10. 从文件中加载镜像

    1
    $ docker load -i nginx-alpine.tar
  11. 部署带认证的镜像仓库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 创建 Docker Registry 认证文件目录
    mkdir /var/lib/registry_auth

    # 使用 htpasswd 来创建加密文件
    yum install -y httpd-tools
    htpasswd -Bbn admin admin > /var/lib/registry_auth/htpasswd

    ## 使用docker镜像启动镜像仓库服务
    docker run -p 5000:5000 \
    --restart=always \
    --name registry \
    -v /var/lib/registry:/var/lib/registry \
    -v /var/lib/registry_auth/:/auth/ \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
    -d registry
  12. 推送本地镜像到镜像仓库中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    ## 镜像仓库给外部访问,不能通过localhost,尝试使用内网地址172.21.51.143:5000/nginx:alpine
    docker tag nginx:alpine 172.21.51.143:5000/nginx:alpine
    docker push 172.21.51.143:5000/nginx:alpine
    The push refers to repository [172.21.51.143:5000/nginx]
    Get https://172.21.51.143:5000/v2/: http: server gave HTTP response to HTTPS client
    ## docker默认不允许向http的仓库地址推送,如何做成https的,参考:https://docs.docker.com/registry/deploying/#run-an-externally-accessible-registry
    ## 我们没有可信证书机构颁发的证书和域名,自签名证书需要在每个节点中拷贝证书文件,比较麻烦,因此我们通过配置daemon的方式,来跳过证书的验证:
    cat /etc/docker/daemon.json
    {
    "registry-mirrors": [
    "https://8xpk5wnt.mirror.aliyuncs.com"
    ],
    "insecure-registries": [
    "172.21.51.143:5000"
    ]
    }
    systemctl restart docker
    docker push 172.21.51.143:5000/nginx:alpine

    # 会提示认证失败 ,no basic auth credentials,需要登录
    docker login 172.21.51.143:5000

    ## 查看仓库内元数据
    curl -u admin:admin -X GET http://172.21.51.143:5000/v2/_catalog
    curl -u admin:admin -X GET http://172.21.51.143:5000/v2/nginx/tags/list

  13. 删除镜像

    1
    docker rmi nginx:alpine
  14. 查看容器列表

    1
    2
    3
    4
    5
    ## 查看运行状态的容器列表
    $ docker ps

    ## 查看全部状态的容器列表
    $ docker ps -a
  15. 启动容器

    1
    2
    3
    4
    5
    6
    7
    8
    ## 后台启动
    $ docker run --name nginx -d nginx:alpine

    ## 映射端口,把容器的端口映射到宿主机中,-p <host_port>:<container_port>
    $ docker run --name nginx -d -p 8080:80 nginx:alpine

    ## 资源限制,最大可用内存500M
    $ docker run --memory=500m nginx:alpine
  16. 容器数据持久化

    1
    2
    3
    ## 挂载主机目录
    $ docker run --name nginx -d -v /opt:/opt nginx:alpine
    $ docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d -v /opt/mysql/:/var/lib/mysql mysql:5.7
  17. 进入容器或者执行容器内的命令

    1
    2
    $ docker exec -ti <container_id_or_name> /bin/sh
    $ docker exec <container_id_or_name> hostname
  18. 主机与容器之间拷贝数据

    1
    2
    3
    4
    5
    6
    7
    8
    ## 主机拷贝到容器
    $ echo 'data'>/tmp/test.txt
    $ docker cp /tmp/test.txt nginx:/tmp
    $ docker exec nginx cat /tmp/test.txt
    data

    ## 容器拷贝到主机
    $ docker cp nginx:/tmp/test.txt ./
  19. 查看容器日志

    1
    2
    3
    4
    5
    6
    7
    8
    ## 查看全部日志
    $ docker logs nginx

    ## 实时查看最新日志
    $ docker logs -f nginx

    ## 从最新的100条开始查看
    $ docker logs --tail=100 -f nginx
  20. 停止或者删除容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ## 停止运行中的容器
    $ docker stop nginx

    ## 启动退出容器
    $ docker start nginx

    ## 删除非运行中状态的容器
    $ docker rm nginx

    ## 删除运行中的容器
    $ docker rm -f nginx
  21. 查看容器或者镜像的明细

    1
    2
    3
    4
    5
    ## 查看容器详细信息,包括容器IP地址等
    $ docker inspect nginx

    ## 查看镜像的明细信息
    $ docker inspect nginx:alpine
文章目录
  1. 1. 认识docker
  2. 2. docker的发展史
  3. 3. docker总结
  4. 4. docker安装
  5. 5. 核心要素
  6. 6. docker基本命令