一、Docker 是什么
Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。
- Docker 使用 Google 公司推出的 Go 语言 进行开发实现。
- Docker 是 Linux 容器的一种封装,提供简单易用的容器使用接口,它是最流行的 Linux 容器解决方案。
- Docker 的接口相当简单,用户可以方便的创建、销毁容器。
- Docker 将应用程序与程序的依赖,打包在一个文件里面。运行这个文件就会生成一个虚拟容器。
程序运行在虚拟容器里,如同在真实物理机上运行一样,有了 docker,就不用担心环境问题了。
二、容器 VS 虚拟机
Docker 是一种OS虚拟化技术,是一个开源的应用容器引擎。它可以让开发者将应用打包到一个可移植的容器中,并且该容器可以运行在几乎所有 Linux 系统中(Windows10目前也原生支持,Win10前需要内置虚拟机),正所谓 “一次打包,到处运行” 。
Docker 容器的运行是完全的沙箱机制,相互之间不会有任何关联(除非自己串联集群)。网络、存储、进程等资源,不仅对于不同的容器是相互隔离,对于宿主机和容器之间也是隔离的,除非你手动映射暴露端口或者挂载存储卷。
差异点
- 每台虚拟机都具备相关应用,必要的二进制类库,是一个完整的操作系统;
- 容器是与宿主机共享硬件资源及操作系统的,可实现资源的动态分配,容器是在宿主机的操作系统上的用户空间层进行的分离. Linux中的容器并不是去模拟一个完整的操作系统,而是对进程进行隔离,相当于是在正常进程的外面套了一个保护层
Docker 的优点
- 更加充分地利用资源;
- 一处打包,到处运行;
- Docker将应用程序与该程序的依赖打包在一个文件里,运行此文件就会生成一个虚拟容器;
- Docker的接口相当简单,并能做到版本管理、复制、分享、修改等;
其他优点
- Docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动。
- Docker 需要的资源更少。Docker 在操作系统级别进行虚拟化,Docker 容器和内核交互,几乎没有性能损耗,性能优于通过 Hypervisor 层与内核层的虚拟化。
- Docker 更轻量。Docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高。
- 与虚拟机相比,Docker 隔离性更弱。Docker 属于进程之间的隔离,虚拟机可实现系统级别隔离。
- 快速创建、删除。虚拟机创建是分钟级别的,Docker 容器创建是秒级别的,Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间;
我们可以从下面这张图中很清楚地看到容器相比于传统虚拟机的特性的优势所在:
三、Docker 的应用场景
- Web应用的自动化打包和发布
- 自动化测试和持续集成、发布
- 在服务型环境中部署和调整数据库或其他应用
四、Docker 的三大概念
Image(镜像)
- Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
- 一个只读的模板,镜像可以用来创建 Docker 容器。
- 用户基于镜像来运行自己的容器。镜像是基于 Union 文件系统的层式结构。
- 可以简单创建或更新现有镜像,或者直接下载使用其他人的。可以理解为生成容器的『源代码』。
Container(容器)
- 容器是从镜像创建的运行实例,在启动的时候创建一层可写层作为最上层(因为镜像是只读的)。
- 可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
- 可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
Repository(仓库)
- 集中存放镜像文件的场所,可以是公有的,也可以是私有的。
- 最大的公开仓库是 Docker Hub。
- 国内的公开仓库包括 Docker Pool 等。
- 当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
- Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。
五、Docker 架构图
- Docker 使用 C/S 结构,客户端/服务器体系结构
- Docker 客户端与 Docker 服务器进行交互
- Docker服务端负责构建、运行和分发 Docker 镜像
- Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTful 、 Stock 或网络接口与远程 Docker 服务端进行通信
各组件说明
- Docker Client
- 提供命令行界面(CLI)工具,是用户与 Docker Daemon 进行交互的主要方式
- Docker Daemon
- 是Docker的服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程
- 用于响应docker client的请求
- 启动: docker --daemon = true 或 docker -d=true
- 默认情况下docker daemon只响应来自本地的请求,若需要响应远程的请求需修改配置
- 配置文件: /etc/systemd/system/multi-user.target.wants/docker.service
- 修改环境变量 ExecStart 后面添加 -H tcp://0.0.0.0
- 请求远程服务器: docker -H remote-host cmds...
- Docker Image
- 是一种特殊的文件系统
- 提供了容器运行时所需的程序、库、资源、配置文件,以及一些运行时相关的配置参数(如匿名卷、环境变量、用户等)
- 镜像文件是只读的,是一个存储在本地磁盘上的物理文件,无相关动态数据
- 镜像的创建:
- 基于Dockerfile生成
- 从仓库下载
- 构建运行的容器以创建镜像
- Docker Container
- 是真正运行项目程序、消耗系统资源、提供服务的地方
- 是真正干活的那个大兄弟
- Docker Registry
- 是Docker Image的存储仓库
六、Docker 安装部署
各系统安装文档
- mac: https://docs.docker.com/docker-for-mac/install/
- windows: https://docs.docker.com/docker-for-windows/install/
- centos: https://docs.docker.com/install/linux/docker-ce/centos/
- ubuntu: https://docs.docker.com/install/linux/docker-ce/ubuntu/
- docker 官方提供的安装测试脚本: https://github.com/docker/docker-install
Centos 安装
- 移除旧版本 docker
> yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
- 安装相关依赖包
> yum install -y yum-utils device-mapper-persistent-data lvm2
- 安装 docker
> yum install docker
- 启动 docker 服务
> service docker start
- 测试
> docker run hello-world
run hello-world 执行过程
- Docker Client 执行 docker run 命令
- Docker Daemon 发现本地没有 hello-world 镜像
- Docker Daemon 从 Docker Registry(Docker Hub) 下载镜像
- 下载完成,镜像 hello-world 被保存到本地
- Docker Daemon 启动容器
镜像加速器
- https://yq.aliyun.com/articles/29941
- https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
七、Docker 相关命令
1、镜像命令
- docker images
- 列出本地的镜像,展示本地镜像列表
- 各列含义
- REPOSITORY 镜像名称
- TAG 标签
- IMAGE ID 镜像的id
- CREATED 创建时间
- SIZE 镜像大小
- 常用选项
- "-a":列出本地所有镜像
- "-q":只展示镜像的id
- "--digests":显示镜像的摘要信息
- "--no-trunc":显示完整的镜像信息
- docker search nginx(镜像名)
- 查询名称为 “nginx” 的镜像
- 是查询的远程仓库:https://hub.docker.com/
- 常用选项
- "--filter=stars=1024":starts数大于1024
- eg: > docker search --filter=stars=1024 nginx
- eg: > docker search -f=stars=1024 nginx # 短格式写法
- 老选项:"-s", 已不推荐, eg: >docker search -s 1024 nginx
- "--no-trunc":显示完整的镜像信息
- "--automated":只展示automated build类型镜像,即列"AUTOMATED"显示为[OK]
- docker pull nginx[:tag]
- 从远程仓库下载拉取镜像 nginx,标签名可选,不选则拉取 latest 版本,即 nginx:latest
- eg: > docker pull nginx:1.18
- docker rmi imageName[:tag]|imageId
- rmi=remove image,删除镜像
- 基于镜像名字或镜像 id 删除,tag选填,默认是 latest
- eg:> docker rmi nginx:latest
- eg:> docker rmi 89749ed4f17d
- 常用选项
- "-f": 强制删除,,如果镜像已被容器使用,此时会删除失败,可用此选项强制删除
- 其他操作
- 强制删除多个: docker rmi -f imageName1|imageId1 imageName2|imageId2
- eg: > docker rmi -f nginx:1.18 nginx:latest
- 强制删除全部: docker rmi -f $(docker images -qa)
- rmi=remove image,删除镜像
2、容器命令
- docker run [options] imageName|imageId [command] [args]
- 基于镜像名来启动容器
- 常用选项:
- "--name":为新容器命名
- "-d":d=daemon 即守护式启动容器,后台运行,返回容器 id
- docker run -d --name nginx002 -p8000:80 nginx
- '-P':P=Port, 随机分配一个端口号
- "-p":p=port, 指定端口映射,一般格式如下:
- ip:hostPort:containerPort
- ip::containerPort
- hostPort:containerPort
- containerPort
- docker 容器交互式运行
- 示例:
- docker run --name centos002 -it centos /bin/bash -c 'while true;do echo 正在运行; sleep 1;done'
- "-i":i=interaction,即交互模式运行容器,一般与"-t"一同使用
- "-t":t=terminal,即终端,运行容器后分配一个输入终端,一般与"-i"一同使用
- /bin/bash :指定使用 centos 的 bash 解释器
- -c:运行一段shell命令
- "while true;do echo 正在运行; sleep 1;done":每秒中打印一次“正在运行”
- 示例:
- docker run -it --name xyz-container imageName
- docker run -it --name my-nginx -p 8080:80 nginx
- 8080是宿主机为应用开启的端口
- 80是docker内nginx的端口
- docker start containerName|containerId
- 启动容器,已经关闭的容器再重新启动
- docker start nginx001
- docker restart containerName|containerId
- 重启容器
- docker restart nginx001
- docker stop containerName|containerId
- 停止容器,优雅停止
- docker stop nginx001
- docker kill containerName|containerId
- 强制停止
- docker kill nginx001
- docker exit
- 容器停止并退出
- control+P+Q,退出但不停止
- docker ps [options]
- 查看当前运行中的容器
- 常用选项
- "-a": 展示当前正在运行的容器和历史运行过的容器
- "-q": 只展示容器的id
- "-l": 显示最近创建的容器
- "-n": 显示最近n个创建的容器
- "--no-trunc": 显示完整的容器信息
- docker rm containerName|containerId
- 删除容器
- 常用选项:
- "-f": 强制删除
- 删除所有容器:
- docker rm -f $(docker ps -aq)
- docker logs containerId
- 查看容器运行的日志
- 常用选项:
- "-f" : f=fllow,跟踪打印
- "-t" : t=timestamp, 时间戳
- "--tail" : 显示末尾多少条日志
- 示例: >docker logs -f -t --tail 100 containerId
- docker top containerId
- 查看容器内运行的进程
- docker inspect containerId
- 查看容器内的详细信息
- docker attach containerId
- 进入运行中的容器中
- 直接进入容器启动命令的终端,不会启动新的进程
- 容器在启动时使用了“-d”参数,则使用该命令不能进入
- docker exec containerId [cmds]
- 不进入容器,执行相关命令
- 常用选项:
- "-t": 终端
- "-i": 交互
- 示例:
- docker exec -it 1b6117933bed(containerId) pwd
- docker exec -it 1b6117933bed(containerId) /bin/sh # 此时会进入容器类似于attach
- 可以在容器中打开新的终端,可以启动新的进程
- docker cp containerId:/home/xyz/xxx.log /current/some/where
- 从容器中复制文件到宿主机
- docker commit
- 提交容器,使之成为新的镜像
- 示例:
- docker commit -m='desc info' -a='author' containerId newImageName:tagName
- -m:提交的描述信息
- -a:指定镜像作者
- newImageName:tagName:指定新的镜像名和版本号
3、数据卷命令
- docker run -it -v /current/host/abs/path:/container/some/where imageName
- 若目录不存在会自行新建
- docker run -it --name centos001 -v /test:/tmp centos
- docker run -it -v /current/host/abs/path:/container/some/where:ro imageName
- ro=read only, 只读
- docker run -it --name centos002 -v /test:/tmp:ro centos
- docker run -it -v /current/host/abs/path:/container/some/where --privileged=true imageName
- 报目录无权访问时,加参数--privileged=true
- docker run -it --name centos003 -v /test:/tmp --privileged=true centos
- docker run -d --name new-nginx001 -p 8000:80 -v /test:/test:ro --privileged=true new-nginx:1.0.0
基于 DockerFile 添加
- VOLUME ["/container1/path","/container2/path"]
- 会在 docker 容器内部创建两个数据卷(目录)
- 待运行容器之后,docker 会给分配两个默认的宿主机目录来与此数据卷进行映射
八、DockerFile
DockerFile 是啥
- Dockerfile 是自动构建 Docker 镜像的配置文件
- 用户可以使用 Dockerfile 快速创建自定义的镜像
- Dockerfile 中的命令非常类似于 Linux 下的 Shell 命令
DockerFile->Image->Container 三者之间的区别
- Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的
- Dockerfile 是由一行行命令语句组成,并且支持已 # 开头的注释行
DockerFile的组成
- 基础镜像(父镜像)信息指令 FROM
- 维护者信息指令 MAINTAINER
- 镜像操作指令 RUN 、EVN 、ADD 和 WORKDIR 等
- 容器启动指令 CMD 、ENTRYPOINT 和 USER 等
Dockerfile常用指令
- FROM
- 一般用于指定基础依赖镜像
- 格式: FORM imageName:tag
- MAINTAINER
- 创建者和联系方式
- 格式: MAINTAINER name <email>
- COPY
- 用于复制本地主机(为 Dockerfile 所在目录的相对路径)的文件到容器中
- 当使用本地目录为源目录时,推荐使用 COPY 。一般格式为 COPY
- 示例: COPY /home/none/data /app # 复制宿主机的 /home/none/data 到容器的 /app 目录下
- ADD
- ADD 命令的格式和 COPY 命令相同
- 除了不能用在 multistage 的场景下,ADD 命令可以完成 COPY 命令的所有功能
- 并且还可以完成如下功能:
- 解压压缩文件并把它们添加到镜像中
- WORKDIR
- 用于配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径
- 格式: WORKDIR /tmp
- RUN
- 用于容器内部执行命令
- RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化
- 格式: RUN <command> 或 RUN ["", "", ""]
- EXPOSE
- 用来指定容器对外开放的端口,在容器启动时需要通过 -p 做端口映射
- 示例: EXPOSE 8080
- ENV
- 指定环境变量,会被RUN指令使用,并在容器运行时保存
- 格式:ENV <key> <value>
- ENTRYPOINT
- 容器启动后执行的命令,并且不会被 docker run 提供的参数覆盖
- 一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效
- 示例: ENTRYPOINT ["command", "param1", "param2"]
- CMD
- 用于启动容器时默认执行的命令,但是会被 docker run 提供的参数覆盖
- 可以包含可执行文件,也可以不包含可执行文件
- 一个 Dockerfile 中只能有一个 CMD,如果有多个,则最后一个生效
- USER
- 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户
- 格式:USER daemon
- VOLUME
- 设置容器的挂载点
- 格式:VOLUME ["/data1","/data2"] 或 VOLUME /data1 /data2
- 提示:启动容器时,Docker Daemon会新建挂载点,并用镜像中的数据初始化挂载点,可以将主机目录或数据卷容器挂载到这些挂载点
示例一:
生成一个修改过的 Docker 镜像,给 nginx 的欢迎页面加一行内容
- 新建镜像文件
FROM nginx MAINTAINER Jack RUN echo '<h1>Hello, Docker!!</h1>' >> /usr/share/nginx/html/index.html
- 构建: > docker build -f nginx.Dockerfile -t jack/nginx:1.0.0 ./
- -f:指定构建的 Dockerfile
- -t:指定生成的镜像名和版本
- ./:Dockfile 所在目录的相对路径,也可以指定绝对路径
- 运行: > docker run --name nginx_test -d -p 8080:80 jack/nginx:1.0.0
- 访问: http://IP:8080/
示例二:
生成一个安装 JDK 并且自动运行 SpringBoot JAR 包的镜像
- 新建镜像文件
FROM centos MAINTAINER Jack ADD jdk-8u212-linux-x64.tar.gz /usr/local ADD gateway-1.0.0-SNAPSHOT.jar /app.jar ENV JAVA_HOME /usr/local/jdk1.8.0_212 ENV PATH $JAVA_HOME/bin:$PATH ENV CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar EXPOSE 8888 ENTRYPOINT ["java","-jar","/app.jar"]
- 构建:docker build -f jdk.dockerfile -t jack/new-jdk-centos:1.0.0 ./
- 运行:docker run --name new-jdk-centos-test -p 8000:8888 jack/new-jdk-centos:1.0.0
- 注意:容器暴露的端口要与 SpringBoot 工程中配置的端口一致,否则外部无法访问
- 发起请求:http://IP:8000/ping