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优缺点
- Docker启动快速属于秒级别。虚拟机通常需要几分钟去启动
- Docker需要的资源更少,Docker在操作系统级别进行虚拟化,Docker容器和内核交互,几乎没有性能损耗,性能优于通过Hypervisor层与内核层的虚拟化
- Docker更轻量,Docker的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker运行的镜像数远多于虚拟机数量。对系统的利用率非常高
- 快速创建、删除,Docker容器创建是秒级别的,虚拟化创建是分钟级别的,Docker的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间
- 隔离性:与虚拟机相比,Docker隔离性更弱,Docker属于进程之间的隔离,虚拟机可实现系统级别隔离
- 安全性:Docker的安全性也更弱。Docker的租户root和宿主机root等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户root权限和宿主机的root虚拟机权限是分离的,并且虚拟机利用如Intel的VT-d和VT-x的ring-1硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击
- 可管理性:Docker的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如VMware vCenter提供完备的虚拟机管理能力
- 高可用和可恢复性:Docker对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡、高可用、容错、迁移和数据保护等经过生产实践检验的成熟保障机制,VMware可承诺虚拟机99.999%高可用,保证业务连续性
- 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化;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
针对不同的镜像,请务必仔细研读官方文档
镜像管理
- 下载镜像
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
- 查看已下载的镜像
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 镜像的所占的磁盘空间
- 删除镜像
docker rmi <repository>:tag / <image id>
(不指定tag默认为latest)
$ docker rmi jenkins
Untagged: jenkins:latest
Untagged: jenkins@sha256:eeb4850eb65f2d92500e421b430ed1ec58a7ac909e91f518926e02473904f668
Deleted: sha256:cd14cecfdb3a657ba7d05bea026e7ac8b9abafc6e5c66253ab327c7211fa6281
...
...
- 镜像打包成tar包
docker save >
,加载镜像docker load <
$ docker save jenkins > jenkins_latest.tar
$ docker load < jenkins_latest.tar
- 给镜像加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
- push镜像到镜像仓库
docker push
容器管理
- 运行容器
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
- 查看容器
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
- 停止
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
- 重启一个已经停止的容器
docker start
$ docker start monkey_jenkins
monkey_jenkins
- 删除容器
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
- 查看容器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
...
...
- 容器交互
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/
- 容器数据持久化,使用参数
-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
容器数据卷的作用:
- 容器数据的持久化
- 容器之间继承和共享数据
- 获取容器/镜像的元数据
docker inspect
如获取如上容器的元数据:docker inspect monkey_jenkins
或docker 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
因为容器是有隔离性的。如果容器之间需要互相链接可以用什么方式呢?--link
这个参数的作用就是把一台容器的网络信息,注入到另外一台容器中。如在搭建testlink服务时需要链接数据库
- 启动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
- 启动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
- 查看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 进行通讯的。
其他
- 查看docker 的信息
docker info