docker介绍,安装及常用命令

虚拟机和docker


左边为虚拟机,右边为docker环境
容器与虚拟机有着类似的资源隔离和分配的优点,但不同的架构方法使容器能够更加便携,高效等

每个虚拟机都包括应用程序、必要的二进制文件和库以及一个完整的客户操作系统(Guest OS),尽管它们被分离,它们共享并利用主机的硬件资源,将近需要十几个 GB 的大小

docker容器中是没有独立的os,而是与宿主机共用同一个内核。然后通过隔离技术,让我们在进入每一个容器时,所看到的内容和操作的环境就像是在一个虚拟机中一样,包括应用程序及其所有的依赖。它们以独立的用户空间进程形式运行在主机操作系统上。他们也不依赖于任何特定的基础设施,Docker 容器可以运行在任何计算机上,任何基础设施和任何云上

虚拟机

如上左图,Server为物理机服务器,Host OS为构建的操作系统。Hypervisor的软件是虚拟机最主要的部分,它通过硬件虚拟化功能,模拟出了运行一个操作系统需要的各种硬件,比如CPU、内存、I/O设备等等。然后它在这些虚拟的硬件上安装了一个新的操作系统(虚拟化的操作系统),即Guest OS。
这样,用户的应用进程就可以运行在这个虚拟的机器中,它能看到的自然也只有Guest OS的文件和目录,以及这个机器里的虚拟设备。这就是为什么虚拟机也能起到将不同的应用进程相互隔离的作用

docker

如上右图,Docker Engine的软件替换了Hypervisor,Docker Engine跳过虚拟化内核的步骤,直接使用宿主机内核

docker优缺点

  1. Docker启动快速属于秒级别。虚拟机通常需要几分钟去启动
  2. Docker需要的资源更少,Docker在操作系统级别进行虚拟化,Docker容器和内核交互,几乎没有性能损耗,性能优于通过Hypervisor层与内核层的虚拟化
  3. Docker更轻量,Docker的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker运行的镜像数远多于虚拟机数量。对系统的利用率非常高
  4. 快速创建、删除,Docker容器创建是秒级别的,虚拟化创建是分钟级别的,Docker的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间
  5. 隔离性:与虚拟机相比,Docker隔离性更弱,Docker属于进程之间的隔离,虚拟机可实现系统级别隔离
  6. 安全性:Docker的安全性也更弱。Docker的租户root和宿主机root等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户root权限和宿主机的root虚拟机权限是分离的,并且虚拟机利用如Intel的VT-d和VT-x的ring-1硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击
  7. 可管理性:Docker的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如VMware vCenter提供完备的虚拟机管理能力
  8. 高可用和可恢复性:Docker对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡、高可用、容错、迁移和数据保护等经过生产实践检验的成熟保障机制,VMware可承诺虚拟机99.999%高可用,保证业务连续性
  9. 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化;Docker在Dockerfile中记录了容器构建过程,可在集群中实现快速分发和快速部署

Docker安装

这里只介绍Docker for Mac的方式,如阿里云操作文档中推荐,对于10.10.3以上的用户 推荐使用Docker for Mac来安装

mac dmg软件包安装比较简单,直接点击安装即可。其他系统可参看阿里云镜像加速器操作文档

  • 配置镜像加速器
    由于众所周知的原因,国内一般都会配置国内的镜像加速器,这里以配置阿里镜像加速器为例
    • 阿里镜像加速需要注册,进入镜像加速器那一栏里会为你独立分配一个加速器地址如https://xxxx.mirror.aliyuncs.com
    • 然后在任务栏点击 Docker Desktop 应用图标 -> Perferences,在左侧导航菜单选择 Docker Engine,在右侧输入栏编辑 json 文件。将分配给你的https://xxxx.mirror.aliyuncs.com加到"registry-mirrors"的数组里(该数组中可添加多个),点击 Apply & Restart按钮,等待Docker重启并应用配置的镜像加速器
    • 其他加速可参看其他文章如
Docker官方的中国镜像加速器:https://registry.docker-cn.com(好像现在不能用了, 可自行尝试)
中科大的镜像加速器:https://docker.mirrors.ustc.edu.cn/ 
七牛镜像加速器: https://reg-mirror.qiniu.com
网易云镜像加速器: http://hub-mirror.c.163.com
腾讯云镜像加速器:https://mirror.ccs.tencentyun.com
  • 检查加速器是否生效
$ docker info
...
Registry Mirrors:
    https://docker.mirrors.ustc.edu.cn/
    ...

docker常用命令

这里用docker搭建Jenkins服务来讲解docker的常用命令(注意,jenkins官方已经迁移到jenkins/jenkins

针对不同的镜像,请务必仔细研读官方文档

镜像管理

  1. 下载镜像 docker pull 及下载指定版本镜像 docker pull <images_name>:version
$ docker pull jenkins
Using default tag: latest
latest: Pulling from library/jenkins
55cbf04beb70: Pull complete
...
...
  • 指定版本
$ docker pull jenkins:2.60.3
  1. 查看已下载的镜像 docker images
docker images
REPOSITORY     TAG       IMAGE ID       CREATED         SIZE
jenkins        latest    cd14cecfdb3a   2 years ago     696MB

REPOSITORY 镜像名;TAG 镜像的版本号,默认latest;IMAGE ID 镜像的唯一标识ID;CREATED 镜像的制作时间;SIZE 镜像的所占的磁盘空间

  1. 删除镜像 docker rmi <repository>:tag / <image id>(不指定tag默认为latest)
$ docker rmi jenkins
Untagged: jenkins:latest
Untagged: jenkins@sha256:eeb4850eb65f2d92500e421b430ed1ec58a7ac909e91f518926e02473904f668
Deleted: sha256:cd14cecfdb3a657ba7d05bea026e7ac8b9abafc6e5c66253ab327c7211fa6281
...
...
  1. 镜像打包成tar包docker save >,加载镜像docker load <
$ docker save jenkins > jenkins_latest.tar
$ docker load < jenkins_latest.tar
  1. 给镜像加tag或改名称 docker tag
$ docker tag jenkins:latest myjenkins:1.0.0
$ docker images
myjenkins      1.0.0     cd14cecfdb3a   2 years ago     696MB
jenkins        latest    cd14cecfdb3a   2 years ago     696MB
$ docker rmi myjenkins:1.0.0
Untagged: myjenkins:1.0.0
  1. push镜像到镜像仓库docker push

容器管理

  1. 运行容器docker run
Run参数 含义
--name 指定容器名称
-d 后台运行
-port/-p 指定端口映射规则
--network/--net 指定容器运行的网路模式
-v 指定需要挂载的数据卷
--env/-e 指定需要传递给容器的环境变量
$ docker run --name monkey_jenkins -p 8080:8080 -d jenkins
e1f2741cb2997b573a027419325e74a0ae2c8dde2f12dc9c6e96a923b5273ddc
  • 交互式运行docker run [options] images /bin/bash
  1. 查看容器docker ps
$ docker ps -s
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                                                  NAMES            SIZE
e1f2741cb299   jenkins               "/bin/tini -- /usr/l…"   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 50000/tcp   monkey_jenkins   2.2MB (virtual 698MB)

CONTAINER ID 容器ID(和image ID无关);IMAGE 启动容器的镜像;COMMAND 容器的启动命令;CREATED 创建时间;STATUS 当前状态;PORTS 容器对外暴露的端口号;NAMES 容器名称

  • docker ps -q:静默模式,只展示容器ID
  1. 停止docker stop及杀死容器docker kill
  • docker ps -a:查看所有的容器,默认情况下仅展示运行中的容器
$ docker ps
$ docker stop e1f2741cb299
e1f2741cb299
$ docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS                       PORTS                                         NAMES
e1f2741cb299   jenkins               "/bin/tini -- /usr/l…"   12 minutes ago   Exited (143) 4 minutes ago                                                 monkey_jenkins
  1. 重启一个已经停止的容器docker start
$ docker start monkey_jenkins
monkey_jenkins
  1. 删除容器 docker rm [-f],如果容器在运行中,可通过-f参数强行删除,否则先docker stop
$ docker rm monkey_jenkins
Error response from daemon: You cannot remove a running container e1f2741cb2997b573a027419325e74a0ae2c8dde2f12dc9c6e96a923b5273ddc. Stop the container before attempting removal or force remove
$ docker rm -f monkey_jenkins
  1. 查看容器log docker logs -f
# 登录http://localhost:8080/则可进入jenkins,但是Administrator password,这个password在哪查看呢
$ docker logs -f monkey_jenkins
...
...
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

013c94675b65425db753b031c92d6dba

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
...
...
  1. 容器交互docker exec -it <container_name>
    # 进入容器
    docker exec -it <container_name> bash
    # 拷贝文件到容器中,同理拷贝容器中的文件到宿主机上
    docker cp <file_path> <container_name>:<container_path>
    

-i (--interactive)表示交互式执行, -t(--tty) 产生一个终端,-it 一般是搭配使用的
ctrl+d 退出容器

  • 如进入jenkins查看Administrator password
$ docker exec -it monkey_jenkins bash
jenkins@e1f2741cb299:/$ cat /var/jenkins_home/secrets/initialAdminPassword
013c94675b65425db753b031c92d6dba
  • 拷贝宿主机数据mirror-adapter.crt$JENKINS_HOME/war/WEB-INF/update-center-rootCAs中
$ docker cp ~/Desktop/mirror-adapter.crt monkey_jenkins:/var/jenkins_home/war/WEB-INF/update-center-rootCAs/
  1. 容器数据持久化,使用参数-v 宿主机路径:容器路径
    如果docker挂掉,或者被误删除,在docker内产生的数据岂不是丢失了呢?docker是如何进行数据持久化的呢?当我们启动容器时,添加了数据挂载的参数-v 宿主机路径:容器路径,docker就可以通过数据挂载的方式,使容器和宿主机的数据进行同步保存
$ docker run --name monkey_jenkins -p 8080:8080 -itd -v ~/Documents/jenkins_home:/var/jenkins_home jenkins

登录jenkins,创建一些数据,删除容器docker rm -f monkey_jenkins
然后再通过同样挂载的方式启动(执行如上命令),查看数据是否丢失
-itd参数
如果出现挂载权限问题,可执行sudo chown -R 1000:1000 /home/docker/jenkins

容器数据卷的作用:

  • 容器数据的持久化
  • 容器之间继承和共享数据
  1. 获取容器/镜像的元数据docker inspect
    如获取如上容器的元数据:docker inspect monkey_jenkinsdocker inspect <CONTAINER ID>(通过docker ps获取<CONTAINER ID>)
......
......
      "Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/xmly/Documents/jenkins_home",
                "Destination": "/var/jenkins_home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
......
......

环境变量-e

有一些容器启动时,我们需要给他添加一些初始的参数,比如mysql,我们需要给他添加一些初始的账号和密码

$ docker pull mariadb
$ docker run --name monkey_mariadb -v ~/Documents/mariadb:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=monkey_jerry -p 3306:3306 -d mariadb

因为容器是有隔离性的。如果容器之间需要互相链接可以用什么方式呢?--link这个参数的作用就是把一台容器的网络信息,注入到另外一台容器中。如在搭建testlink服务时需要链接数据库

  1. 启动mariadb
$ docker run -d --name mariadb -e ALLOW_EMPTY_PASSWORD=yes -e MARIADB_USER=bn_testlink -e MARIADB_DATABASE=bitnami_testlink -v ~/Documents/mariadb:/var/lib/mysql -p 8088:3306 mariadb
  1. 启动tesklink,将mariadb的信息注入到testlink容器中
$ docker run -d --name testlink -p 8099:80 -p 444:443 -e ALLOW_EMPTY_PASSWORD=yes -e TESTLINK_DATABASE_USER=bn_testlink -e TESTLINK_DATABASE_NAME=bitnami_testlink --link mariadb bitnami/testlink:latest
  1. 查看testlink日志,可以看到成功连接到mariadb

如果是三个容器需要连接呢?使用--env,因为在docker中,--link就是通过环境变量的方式配置的

网络模式--network

在使用 docker run 命令的时候加上 --net--network 参数就可以选择使用的网络模式了, 默认是 bridge 模式,其他的还有 container,host 和 none等,可通过docker info查看docker的Network信息

  • bridge模式
    Docker开发者最常使用的网络模式,如果外网想要访问容器就需要使用端口映射。Brdige桥接模式为Docker Container创建独立的网络栈,保证容器内的进程组使用独立的网络环境,实现容器间、容器与宿主机之间的网络栈隔离。另外,Docker通过宿主机上的网桥(docker0)来连通容器内部的网络栈与宿主机的网络栈,实现容器与宿主机乃至外界的网络通信
  • host模式
    host模式并没有为容器创建一个隔离的网络环境。而之所以称之为host模式,是因为该模式下的Docker Container会和host宿主机共享同一个网络namespace,故Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。换言之,Docker Container的IP地址即为宿主机eth0的IP地址
  • container 模式
    Docker Container共享其他容器的网络环境,则至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离
    我们先启动一个容器 (假如是用 briage 模式启动)。然后启动其他容器如a的时候在 net 或者 network 参数的设置上使 container:a容器名称。 这样后启动的容器都会使用第一个容器的网卡。 也就是说,虽然我们启动的是不同的容器,但他们彼此之前是可以使用 localhost 进行通讯的。

其他

  1. 查看docker 的信息 docker info

参考及扩展阅读

  1. Docker 命令参考文档
  2. Dockerfile 镜像构建参考文档
  3. docker 系列文章
  4. docker和虚拟机
  5. 霍格沃滋Docker 实战分享
  6. 孙高飞-测试开发之路--devops (一):序
  7. 孙高飞-测试开发之路--devops (二):docker 的文件系统
  8. 孙高飞-测试开发之路--devops (三):docker 的网络原理
  9. 孙高飞-测试开发之路--devops (四):docker 的 4 种网络模式
  10. 测试开发之路 POD 衍生知识 (cgroups)
  11. Docker Container网络