Docker入门
什么是Docker
引入Docker
同样的应用在部署时,由于组件较多,运行环境复杂,会遇到类似问题:
- 将不同的软件集成起来的过程中有很多不可控的风险,由于依赖关系复杂,容易出现兼容性问题
- 由于开发、测试、生产环境的差异,一旦需要重新迁移服务器或者重新部署一套环境,还将重新执行一遍
Docker结构
- Docker 将用户程序与所需要调用的系统函数库一起打包
- Docker 在运行到不同操作系统时,直接通过内核创建虚拟的操作系统实例(内核和库),来隔离不同的进程和资源
- Docker 允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像
- Docker 应用运行在容器中,使用沙箱机制,相互隔离
- Docker 镜像中包含完整运行环境,包括系统函数库,仅依赖系统的 Linux 内核,因此可以在任意 Linux 操作系统上运行
Docker主要三大类用途
- 提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境
- 提供弹性的云服务。因为Docker容器可以随开随关,很适合动态扩容和缩容。
- 组建微服务架构。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。
Docker 与 虚拟机
- 虚拟机(virtual machine)是带环境安装的另一种解决方案,它可以在一种操作系统里面运行另一种操作系统
- 应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点:
- 资源占用多,虚拟机会独占一部分内存和硬盘空间
- 冗余步骤多,虚拟机是完整的操作系统,需要经过繁琐的配置
- 启动慢,启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行
Docker 的组成
镜像(Image)
- Docker 把应用程序及其依赖,打包在image 文件里面。只有通过这个文件,才能生成Docker容器。
- image 文件可以看作是容器的模板,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
- Docker 根据 image 文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例。
- 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
- image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而成
- image 文件是通用的,一台机器的 image 文件拷贝到另外一台机器,照样可以使用。
- 为了方便共享,image文件创作完成后,可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。
容器(Container)
- 镜像(Image) 和 容器(Container) 的关系,就像是面对对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。
- 容器是一个独立运行的一个或一组应用,以及它们的运行态环境,容器可以被创建、启动、停止、删除、暂停等
- 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。拥有自己的 root 文件系统、自己的网络配置、进程空间,甚至自己的用户 ID 空间
仓库(Repository)
- 镜像构建完成后,可以很容易在当前宿主机上运行,但是,如果需要在其他服务器上使用这个镜像,就需要一个集中的存储、分发镜像的服务,Docker Registy 就是这样的服务
- 一个 Docker Registy 中可以包含多个仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像
- 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过==<仓库名>:<标签>==的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker架构
- 客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。
- 服务端(server): Docker守护进程,负责处理Docker指令,管理镜像、容器等
安装 Docker
- 参考如下两个网站:
- https://www.runoob.com/docker/centos-docker-install.html
- https://yeasy.gitbook.io/docker_practice/install/centos#shi-yong-yum-an-zhuang
- 对于 “无法ping“、”DNS无法解析“参考下面网站:
- https://blog.csdn.net/whatday/article/details/88791582
- https://www.cnblogs.com/wgying/p/6006609.html
- 安装成功
- 配置Docker 国内镜像加速:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
- 启动 Docker
Docker基础
镜像
镜像操作过程
镜像操作示例
- 访问 DockerHub搜索镜像:https://hub.docker.com/ ,搜索 redis
- 拉取镜像:
docker pull redis:5.0.14
(作者本机版本) - 查看本地镜像:
docker images
- 将镜像导出到磁盘:
docker save -o 文件名称 镜像名称/ID
- 删除本地镜像:
docker rmi 镜像名称/ID
- 导入镜像:
docker load -i 文件名称
容器
容器操作过程
常用操作命令
-
docker run
—- 新建并启动容器 -
docker start/stop/pause/unpause
—- 启动/停止/暂停/恢复容器 -
docker exec
—- 进入容器执行命令 -
docker logs
—- 查看容器运行日志 -
docker ps
—- 查看容器的状态 -
docker rm
—- 删除指定容器
Nginx容器示例
- 拉去 nginx 镜像:
docker pull nginx:1.22.1
(作者本机版本) - 创建并启动容器:
docker run --name mynginx -d -p 80:80 nginx
- —name:指定容器名称
- -p:讲宿主机端口与容器端口映射,格式:宿主机端口:容器端口
- -d:后台运行容器
Redis 容器示例 — 进入容器
- 拉取 redis 镜像:
docker pull redis
- 创建并启动容器:
docker run --name myredis -d -p 6379:6379 redis
- 进入容器:
docker exec -it myredis bash
- -it:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
- bash:进入容器后执行的命令
- 进入容器后执行:
redis-cli
,使用 redis 客户端操作 redis - 可将上面两步骤结合:
docker exec -it myredis redis-cli
关于 Redis 的一些命令(某些可能在Docker中无法使用)
- redis 常用命令
-
redis-server
—- redis 服务器 -
redis-cli
—- redis 命令行客户端 -
redis-benchmark
—- redis 性能测试工具 -
redis-check-aof
—- aof 文件修复工具 -
redis-check-dump
—- rdb 文件检查工具
- 停止 redis 命令
-
redis-cli shutdown
—- 停止 redis 命令
- 启动 redis 命令
-
redis-server
—- 启动 redis-server 服务 -
redis-server ./redis.conf
—- 带配置文件启动 -
redis-server ./redis.conf --daemonize yes --port 1123
—- 带配置文件启动 且指定某几个配置(配置名前加 —)
- redis 命令客户端
-
redis-cli -h 127.0.0.1 -p 1123
—- 在127.0.0.1:1123 端口进行交互
Docker 进阶
Docker 数据卷
容器中的数据问题
- 一个容器运行了一段时间,肯定会产生一些数据,比如日志、数据库数据、新改的配置文件等等,如果这些数据文件存放在容器中,当我们删除容器时,这些数据也会被随之删除
- 在 docker 中,提供了一种存储数据的方法,叫做”数据卷“,可以达到数据共享的目的
基本概念
我们可以把”数据卷“ Data Volumes 理解成”宿主机中的目录“,当把某个卷和容器中的某个目录建立映射关系后,就相当于把宿主机中的某个目录和容器中的某个目录建立了映射关系,如下图所示:
数据卷提供了很多有用的特性:
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;
- 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
- 对数据卷的更新不会影响镜像,解耦开应用和数据;
- 卷会一直存在,直到没有容器使用,可以安全地卸载它。
数据卷操作命令
基本语法为:docker volume [COMMAND]
,其中 COMMAND 可选值:
- create:创建一个 volume;
- inspect:显示一个或多个 volume 的信息
- ls:列出所有的 volume
- prune:删除未使用的 volume
- rm:删除一个或多个指定的 volume
在 linux 的 docker 主机中创建一个卷时,其在宿主机对应的目录(挂载点)路径为 /var/lib/docker/volumes/卷名/_data
挂载卷
在创建容器时,可以通过 —volume 或 -v 参数挂载一个数据卷到某个容器目录:
上述命令表示创建一个名为 testAcon 的容器,将 testA 卷映射到 testAcon 容器的 /data 目录中
==注意:==
- 如果卷映射的目录在容器中不存在时,会自动在容器中创建对应的目录
- 一个容器可以使用多个卷,只需要多次使用 -v 指定选项即可,如:
- 当指定的卷不存在时,docker 会自动创建对应的卷,上述命令中的 testB 数据卷会被自动创建
绑定挂载
前面创建的数据卷都存放在 /var/lib/docker/volumes
目录中,这个目录时固定的,它们都能被 docker volume 命令管理
docker 还有一种映射宿主机目录的方法,这种方法被称为”绑定挂载“,绑定挂载能够将指定的宿主机目录挂载到容器中,只需要将卷名替换成宿主机上的目录路径即可
- 上述命令将宿主机的
/root/test1
目录映射到容器的 /data1
目录中 - 绑定挂载不会生成任何卷,它直接将指定的宿主机目录映射到容器中,所以,docker volume 命令无法查看或管理到绑定挂载的路径
==!!!重要!!!!==
- 官方建议使用卷,而不是绑定挂载。但是,绑定挂载有一个优势,就是绑定挂载可以直接将宿主机中的文件(非目录)直接挂载到容器中,比如,将宿主机中的
/etc/localtime
文件映射到容器中的 /etc/localtime
文件
- 通常,使用绑定挂载就是为了将宿主机中的配置文件挂载到容器中,如果时整个目录的数据,建议使用卷,卷只能映射目录,不能映射文件。
nginx示例
- 创建容器并挂载数据卷到容器内的 HTML 目录
- 进入 html 数据卷所在位置,并修改 HTML 内容
Docker 自定义镜像
镜像的内部结构
对于 Docker 用户来说,最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等现有的 Docker 官方镜像或其他人和组织创建的镜像,我们只需要稍作配置就可以直接使用。
某些情况下我们也不得不自己构建镜像,比如:
- 找不到现有的镜像,比如自己开发的应用程序
- 需要在镜像中加入特定的功能
Dockerfile
Dockersfile 是镜像的描述文件,定义了如何构建 Docker 镜像,hello-world 的 Dockerfile:
- FROM scratch:表示镜像白手起家,从 0 开始构建
- COPY hello /:将文件 ”hello“ 复制到镜像的根目录
- CMD [“/hello”]:启动容器时,执行 /hello
镜像 hello-world 中就只有一个可执行文件”hello“,其功能就是打印出 ”Hello from Docker….“等信息
base 镜像
- 通常来说,我们希望镜像能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。这样的镜像我们称作 base 镜像
- base 镜像有两层含义:
- 不依赖其他镜像,从 scratch 构建
- 其他镜像可以以之为基础进行扩展
- 能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu、Debian、CentOS等
- 下载 CentOS镜像:
docker pull centos
CentOS 的 Dockerfile
base 镜像提供的是最小安装的 Linux发行版,CentOS 镜像的 Dockerfile 的内容:
- ADD 指令添加到镜像的 tar 包就是 CentOS 7的rootfs。在制作镜像时,这个 tar 包会自动解压到 / 目录下,生成 /dev、/proc、/bin 等目录
- 可在Docker Hub 的镜像描述页面中查看 Dockerfile。
为何系统镜像如此小
Linux 操作系统由内核空间和用户空间组成:
- 内核空间是 Kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉
- 用户空间的文件系统时 rootfs,包含我们熟悉的 /dev、/proc、/bin 等目录
- 对于base镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了
- 一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。alpine不到10MB
通过 Dockerfile 构建镜像
Dockerfile中常用命令
制作 Java 应用镜像示例
基于 CentOS 基础镜像构建 Java 应用镜像
1.上传 JDK
创建文件夹,将 jdk 安装包上传到该目录下
2.编写 dockerfile
在 /root/dockerfile/java 目录下创建文件 dockerfile_java,内容如下:
3.生成镜像
SHELL
复制成功
|
|
4. 验证镜像是否生成成功
SHELL
|
|
5. 启动容器
SHELL
|
|
通过 Java 镜像构建应用镜像
1.编写dockerfile
DOCKERFILE
|
|
2.生成镜像
SHELL
|
|
3.验证镜像是否生成成功
SHELL
|
|
4.启动容器
SHELL
|
|
示例结果