1. Docker是什么?
Docker是一个用来装应用的容器,就好比用书包来装书,用水杯来装水,你可以把你想到的任何应用程序放到Docker里
2. Docker特点
2.1 组织有序性
以传统方式部署应用,可能会出现两个应用依赖同一程序的不同版本。使用Docker可以方便管理各个应用的的依赖,并以容器为基础将各个应用的运行环境独立开来,从而不会相互影响,还能提高资源利用率
2.2 便捷性
应用的后期迁移,大规模集群都非常的方便
2.3 安全性
容器的资源和系统是隔离的
Docker VS VM
类别 | Docker | VM |
---|---|---|
操作系统 | 与宿主机功效OS | 在宿主机OS运行虚拟OS |
部署难度 | 非常简单 | 组件多,部署复杂 |
启动速度 | 秒级 | 分钟级 |
执行性能 | 与物理系统几乎一致 | VM会占用一些资源 |
镜像体积 | MB | GB |
管理效率 | 管理简单 | 组件相互依赖,管理复杂 |
隔离性 | 比较弱 | 彻底 |
资源消耗 | 很小,轻松创建多个容器 | 很大 |
操作系统覆盖 | 仅仅是内核所支持的OS | 支持Linux、Mac、Window等 |
3. Container的核心技术
3.1 CGroup限制容器的资源使用
Linux内核提供的限制,记录和隔离进程组所使用的资源.由Google的工程师提出,后台被整合到内核中.
通过不同的子系统来实现对不同资源使用的控制和记录.
/sys/fs/cgroup
3.2 Namespace机制,实现容器间的隔离
pid:容器有自己独立的进程表和1号线程.
net:容器有自己独立的network info
ipc:在ipc通信的时候,需要加入额外信息来标示进程
mnt:每个容器都有自己唯一的目录挂载
utc:每个容器都有独立的hostname和domain
3.3 chroot,文件系统的隔离.
在宿主机中的某个目录就是容器中的根目录
4 容器的基本概念
docker三大重要概念:仓库、镜像、容器
4.1 仓库(repository)
仓库适用于存放镜像的地方,类似于Maven、git仓库等。一个仓库注册服务器(Registry)用多个仓库,一个仓库有多个镜像,一个镜像有多个标签(tag),目前最大的公开仓库是Docker Hub
4.2 镜像(Image)
可以理解为一个只读模板,镜像可以用来创建仓库,一个镜像可以创建多个容器,也可以从官方仓库(docker hub)或者其他私服仓库拉取(pull)想要的镜像,或者通过哦Dockerfile文件来构建属于自己的镜像
4.3 容器(Container)
容器是由镜像创建的实例,可以被启动、停止、运行、删除。每个容器相互隔离,也可以把容器看做一个简单的Linux环境
5. 安装Docker
Docker安装相对简单,不过官方要求CentOS操作系统内核(uname -r)必须在3.10以上,我这里使用CentOS7来安装
1. 更新yum仓库,确保yum包都是最新的
yum update
2. 检查是否安装过Docker,若有将其删除
yum list installed | grep docker
yum remove docker...#如果有则删除
3. 安装需要的软件包,yum-util 提供 yum-config-manager 功能,另外两个是 devicemapper 驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
4. 设置 yum 源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
5. 查看仓库中所有 docker 版本,选择你需要的版本安装
yum list docker-ce --showduplicates | sort -r
6. 安装 docker
yum install -y docker-ce
7. 设置 docker 开机自动启动
systemctl start docker # 启动 docker 服务端
systemctl enable docker # 启用 docker 服务开机自启
8. 校验 docker 是否启动成功
docker version
6. 容器的基本操作
6.1. 启动容器
docker run IMAGE [COMMAND] [ARGS]
docker run centos echo 'hello docker'
run 命令解释:
1.1. 命令会检查当前要运行的镜像在本地存不存在,若不存在他会自动 pull 下来再运行
1.2. 运行后会启动一个容器, 并且开启一个文件系统, 你可以直接在容器内创建文件夹. 运行一个指定的程序, 当程序退出后, 容器也就退出了
1.3. 运行时的容器无法删除, 只能停止后删除, 或者加上 -f 参数强制删除
6.2. 启动守护式容器
1.docker run --name 自定义容器名称 -it IMAGE /bin/bash
2.docker run --name 自定义容器名称 -itd IMAGE /bin/bash
参数说明:
--name
给容器取一个自定义的名称
-i
交互式操作
-t
终端
-d
默认不会进入容器
/bin/bash
交互式Shell
6.3. 退出容器
进入容器使用:
-
docker attach '容器的名称 | 容器的唯一标识'
Ctrl+PQ
退出不关闭容器
exit
退出关闭容器 -
docker exec -it '容器的名称 | 容器的唯一标识' /bin/bash
(推荐使用)
Ctrl+PQ
退出不关闭容器
exit
退出不关闭容器
image.png
6.4 查看容器
docker ps [-a] [-l]
参数说明:
-a
列举所有容器
-l
列举最近创建的容器
默认情况下容器运行之后欧就停止了,ps只显示正在运行的容器
6.5 查看容器详细信息
docker inspect [容器的名称 | 容器的唯一标识]
6.6 重新启动停止的容器
docker start [-i] 容器名
6.7 删除停止的容器
docker rm 容器名
docker rm $(docker ps -qa)
删除所有
6.8 查看容器日志
docker logs [-f] [-t] [--tail] 容器名
参数说明:
-f
--follow=true|false 默认为false 一致跟踪日志的变化,并返回结果
-t
--timestamps=true|false 默认为false 在返回的结果上加上时间戳
--tail
= “all” 返回后几行的日志数据
6.9 查看容器内的进程
docker top 容器名
6.10 在运行的容器内启动新的进程
docker exec -itd 容器名 [command] [arg...]
如下图,关闭和启动Nginx
6.11 停止守护式容器
docker stop 容器名
发送一个信号给容器,等待容器的关闭
docker kill 容器名
直接停止容器
7 部署静态网站
7.1 设置容器的端口映射
run [-P] [-p]
参数说明:
1 -P
, --publish-all=true|false 默认为false :将为容器所有暴露的端口进行映射,容器内部使用的网络端口映射到我们使用的主机上
示例:docker run -P -i -t centos /bin/bash
2 -p
, --publish=[] :给指定的端口进行映射
docker run -p 80 centos /bin/bash
:containerPort
docker run -p 8080:80 centos /bin/bash
:hostPort:containerPort
7.2 部署Nginx
- 创建一个守护式容器,并映射容器的80端口
docker run -p 80 --name 名称 -it centos:7 /bin/bash
- 进入容器后,需要安装nginx和vim,执行如下命令
yum install -y vim
yum install -y wget
#修改centos镜像仓库
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
#安装Nginx
yum install -y epel-release
yum install -y nginx
#运行Nginx
/usr/sbin/nginx
#退出容器
Ctrl+PQ
在宿主机中使用curl命令查看是否能访问
curl http://127.0.0.1:32769/index.html
注意:
当容器重新启动会重新给我们进行端口映射
8 Docker镜像和仓库
Docker Image镜像:1. 容器的基石,2.层叠的只读文件系统,3.联合加载
-
docker images [OPTIONS] [REPOSITORY]
:列出镜像
参数说明:
-a
, --all=false :表示列举出所有的镜像.默认并不显示中间层的镜像.
-f
, --filter=[] :表示添加过滤条件.
--no-trunc=false
:表示对信息进行截断.默认情况是会截断镜像的唯一id的.
-q
, --quiet=false:表示值显示镜像的唯一id
REPOSITORY 仓库
:是一切镜像的集合
REGISTRY 注册仓库
:包含REPOSITORY的仓库
TAG 标签
:之前运行的centos默认使用lastest的标签。仓库名+标签就能唯一确定一个镜像
如果使用docker images -a 看到没有仓库名和标签名的其实是中间层镜像 -
docker inspect [OPTIONS] CONTAINER | IMAGE [CONTAINER | IMAGE...]
:查看镜像 -
docker rmi [OPTIONS] IMAGE [IMAGE...]
:删除镜像 -
docker rmi $(docker image -q centos)
:删除对应仓库的所有镜像
参数说明:
-f
, --force=false :表示强制删除镜像.
--no-proune
=false :会保留未被打标签的父镜像
9 获取和推送镜像
Docker中REGISTER仓库有些类似Maven的中央仓库.我们通过类似Git中的pull和push命令从REGISTER仓库中拉取镜像和推送镜像
- 查找镜像
方式一:
Docker Hub:http://hub.docker.com/
方式二:
docker search [OPTIONS] TERM
-no-trunc=false : 截断操作
-s,--starts=0 : 每个镜像都会有star,我们可以通过-s操作来限定star数 - 获取镜像
docker pull [OPTIONS] name[:TAG]
示例: docker pull centos:7
可以发现下载速度非常慢,这时可以是用镜像加速器(daocloud或者阿里云-控制台-搜索镜像加速器-按照说明配置)
- 推送镜像
docker push 镜像名
步骤:
1. 注册hub账号
2.登陆hub的账号.docker login
3.使用push命令推送到hub中
10 构建镜像
- 方式一:
docker commit -m='描述信息' -a='作者' srcDockerID desDockerName:version
- 方式二:
docker build [OPTIONS] PATH|URL|-
--force-rm=false
--no-cache=false
--pull=false
-q, --quiet=false
-rm=true
-t, --tag=””
使用Dockerfile构建镜像的步骤:
1. 在宿主机中,创建存放Dockerfile文件的目录和Dockerfile文件
mkdir -p dockerfile/df_test1/
cd dockerfile/df_test1/
vi Dockerfile
2. 编写Dockfile文件
# First docker file for test
FROM centos
MAINTAINER xxx "lxxx"
RUN yum install -y wget
RUN wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum install -y epel-release
RUN yum install -y nginx
EXPOSE 80
3. 使用build命令构建镜像
docker build -t='df_test1'
4. 通过构建好的镜像来创建容器
docker run -d --name nginx_web3 -p 80 df_test1 /usr/sbin/nginx -g "daemon off;"
11 Dockerfile指令格式
指令主要分为两种:
注释 : # Comment
指令 : INSTRUCTION argument
FROM:
包含两种格式:
1. FROM <image>
2. FROM <image>:<tag>
image要求是已经存在的镜像,我们也称为基础镜像.必须是第一条非注释指令
MAINTAINER:
指定镜像的作者信息,包含镜像的所有者和联系信息.
RUN:
指定当前镜像中运行的命令
RUN <command> (shell模式)
/bin/sh -c command
RUN echo hello
RUN [“executable”,”param1”,”param2”] (exec模式)
RUN [“/bin/bash”,”-c”,”echo hello”]
每个RUN命令都会在当前镜像的上层创建一个新的镜像来运行指令.
EXPOSE:
指定运行该镜像的容器使用的端口.
虽然我们在构建镜像的时候暴露了端口号,但是我们在运行容器的时候依然需要指定端口的映射.
我们使用EXPOSE只是告诉Docker运行该镜像的容器会使用80端口,出于安全的考虑,docker并不会打开该端口.
而是需要我们在使用该镜像运行容器的时候指定端口的映射.
CMD:
CMD指令提供容器默认运行的命令,和之前讲的RUN指令类似.都是执行一个命令,但是RUN命令指定的命令是在镜像构建的过程运行的.
CMD的命令是在容器运行的时候运行的.如果我们在docker run命令中指定运行的命令的时候,CMD的指令会被覆盖,默认命令就不会执行.
CMD命令是指定容器启动的时候默认命令.
两种模式.
CMD [“executable”,”param1”,”param2”] (exec模式)
CMD command param1 param2 (shell 模式)
CMD [”param1”,”param2”] (作为ENTRYPOINT指令的默认参数.)
示例:
通过构建的镜像来创建容器
docker run -p 80 --name cmd_test1 -itd df_test3
docker top cmd_test1
发现已经启动nginx了.
如果我们在启动的时候指定了参数,默认的CMD命令就会被覆盖了.
ENTRYPOINT:
这个和我们刚刚讲的CMD指令非常相似,唯一的区别:不会给docker run的启动命令给覆盖.
如果需要覆盖ENTRYPOINT的指令,需要在docker run使用docker run --entrypoint覆盖.
ENTRYPOINT [“executable”,”param1”,”param2”] (exec模式)
ENTRYPOINT command param1 param2 (shell 模式)
示例:
docker build -t="df_test4" .
docker run -p 80 --name ep_test1 -d df_test4
docker ps -l
可以发现,启动的容器依然使用的ENTRYPOINT指定的命令执行.
ADD:
将文件和目录复制到使用dockerfile构建的镜像中.
目标的来源可以本地的地址也可以是远程地址.
如果是本地地址,本地地址必须是构建目录中的相对地址
对于远程URL,docker并不推荐使用,更建议使用的是curl或者wget的命令来获取
目标路径需要指定镜像中的绝对路径
ADD <src>...<dest>
ADD [“<src>”...”<dest>”](适用于文件路径有空格的情况)
COPY:
同上.
COPY<src>...<dest>
COPY[“<src>”...”<dest>”](适用于文件路径有空格的情况)
示例:
在Dockerfile所在目录添加index.html文件
docker build -t="df_test6" .
docker run -p 80 --name add_test1 -d df_test6
curl http://127.0.0.1:32775
VOLUME:
用于基于镜像创建的容器添加卷,一个卷可以存在一个或者多个容器的特定目录.这个目录可以绕过联合文件系统.提供共享数据和持久化数据的 功能.(后面单独讲)
WORKDIR:
WORKDIR /path/to/workdir
这个指令从指令创建一个容器是,在容器内部设置工作目录.ENTRYPOINT和CMD的命令都会在这个目录下执行.
我们也可以使用这个命令给后续的构建中指定工作目录.
通常会使用绝对路径,如果使用了相对路径,那这个路径会一致传递下去.如下所示:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
结果====>/a/b/c
ENV:
ENV <key><value>
ENV <key><value>...
这个指令主要是来设置环境变量,这个环境变量在构建过程中和运行过程中都有效.
USER:
USER daemon
指定镜像会以什么样的用户去运行.
比如:USER nginx
基于该镜像启动的容器就会以nginx的用户来运行.
如果没有指定USER,容器会使用root用户来运行.
ONBUILD:
ONBUILD [INSTRUCTION]
镜像触发器.
当一个镜像被其他镜像作为基础镜像时执行
会在构建过程中插入指令
示例:
docker run -p 80 --name onbuild_test1 -d df_test7
curl http://127.0.0.1:32776
发现在构建这个镜像的时候并没有执行COPY命令.
接下来我们基于这个镜像来构建新的镜像.
docker build -t="df_test8" .
docker run -p 80 --name onbuild_test2 -d df_test8
curl http://127.0.0.1:32777
此时发现已经执行COPY命令了.
12 Dockerfile构建过程
- 从基础镜像运行一个容器.
- 执行一条指令,对容器做出修改.
- 执行类似docker commit 的操作,提交一个新的镜像层.
- 再基于刚提交的镜像运行一个新容器.
- 执行Dockerfile中的下一条指令,直到所有指令执行完毕.
docker build会删除中间层创建的容器,但是不会删除中间层创建的镜像.我们可以使用docker run 的方式来运行中间层镜像.从而查看每一步创建后的镜像的实际状态,这就给了我们调试镜像的能力.
docker会把之前创建过的中间层镜像建立成缓存,第二次构建的时候其实就直接中缓存中拿到中间层的镜像.但是有些时候我们不想使用缓存.
docker build --no-cache
13 容器的网络基础
docker有四种网络模式。分别是:bridge模式、host模式、container模式、none模式。
在容器运行时,添加一下参数:
-net bridge | host | container | none 选择其中一种
bridge模式:
容器中的环境与宿主机隔离,那么此时容器内与外部进行网络通信就会有些问题,外部不能直接访问容器内的IP地址和端口。
docker 为我们提供了宿主机的端口与容器内的端口映射来解决此问题,方式有两种,一种是随机映射,一种是指定映射。
docker run --name doc-test -it -p 8080:8080 -p 80:80 centos /bin/bash
host模式
如果启动容器的时候使用host模式,那么容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的
container模式
这个模式指定新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的
none模式
使用none模式,Docker容器不会进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等
14 容器之间相互连接
Docker容器互联的默认方式,在同一宿主机上,docker容器是通过虚拟网桥来进行连接的.在默认情况下,在同一宿主机中的所有容器都是可以互相连接的。但是,重启容器发现,容器的地址并不是固定的,如果在容器内部使用的服务是以地址的方式连接的,可能在容器重启的时候就会失效.所以通过地址连接是不可靠的.docker为了避免这种情况,提供了另外一种方式
docker run --link=[CONTAINER_NAME]:[ALIAS] [IMAGE] [COMMAND]
:这样就可以通过别名来访问,避免了ip访问
15 容器的数据管理
什么是数据卷(Data Volume):
我们都知道Docker其中一个理念就是应用和环境打包.通常docker容器的生命周期都是和容器中的应用是一致的.而我们对数据的要求是持久化,另外docker容器之间也需要有一个共享数据的渠道.这些需求就催生了数据卷的需求.
数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或者多个容器提供访问.
数据卷设计的目的,在于数据的永久化,它完全独立与容器的生命周期,因此Docker不会在容器删除的时候删除其关联的数据卷,也不会存在类似垃圾收集机制,对容器应用的数据卷进行处理
为容器添加数据卷:
docker run -v ~/container_data:/data -it centos /bin/bash
为数据卷添加访问权限
docker run -v ~/datavolume:/data:ro -it centos /bin/bash
使用Dockerfile构建包含数据卷的镜像
Dockerfile指令:VOLUME[“/data”]
示例:
# Test
FROM centos
VOLUME ["/datavolume1","/datavolume2"]
CMD /bin/bash
执行构建命令: docker build -t doc:0.01
16 多容器管理(docker-compose)
Dockerfile 用来构建 Docker 镜像,那么 docker-compose 则是用来创建容器的。 Docker 有三个主要的功能:Build、Ship 和 Run,使用 docker-compose 可以帮我们在 Run 的层面解决很多实际问题。docker-compose 通过一个 yaml 模板文件来统一管理多个容器的配置,如网络、数据卷、执行指令、环境变量、资源限制等等。有了 docker-compose 我们便可以一键重启、关闭、删除、监控所有的 docker 服务,只需要一次配置,则可以对容器进行统一管理,那么此时我们则不必为了每次要运行一堆容器时写大量的命令而头疼。
- docker-compose安装
1、安装python-pip
yum -y install epel-release
yum -y install python-pip
2、安装docker-compose
pip install --ignore-installed docker-compose
待安装完成后,执行查询版本的命令确认安装成功
docker-compose version
- 配置docker-compose.yml文件
version: '3' # docker 的版本
services: # 配置的容器列表
CONTAINER_NAME: # 容器的名称
image: BASE_IMAGE # 这个一个容器的基础镜像
ports: # 你的容器需不需要做端口映射
- "host_port:container_port"
volumes: # 数据卷配置
- host_dir:container_dir
environment: # 环境变量(map 的配置方式 key: value)
PARAM: VALUE
environments: # 环境变量(数组的配置方式 - key=value)
- PARAM=VALUE
restart: always # 容器的重启策略
dns: # dns 的配置
- "8.8.8.8"
------------------------------------------------------------------
restart 容器的重启策略:
no:默认策略,在容器退出时不重启容器
on-failure:在容器非正常退出时(退出状态非0),才会重启容器
on-failure:3:在容器非正常退出时重启容器,最多重启3次
always:在容器退出时总是重启容器
unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
- 常用命令
docker-compose up -d # 启动所有服务并在后台运行
docker-compose ps # 查看服务运行状态
docker-compose restart # 重启所有服务
docker-compose restart myApp # 重启 myApp 服务
docker-compose start # 开启所有服务
docker-compose start myApp # 开启 myApp 服务
docker-compose stop # 停止所有服务
docker-compose stop myApp # 停止 myApp 服务
docker-compose rm # 删除所有服务
docker-compose rm myApp # 删除 myApp 服务
网友评论