Docker背景介绍
1. 什么是Docker?
Docker是一种开源的应用容器引擎,允许开发者将应用及其依赖打包成一个可移植的容器,从而能够在任何流行的Linux机器上运行。Docker以其轻量级、快速启动和隔离性质著称,可以实现虚拟化,但与传统虚拟机相比,它几乎没有性能开销。
Docker使用沙盒机制,确保不同容器之间相互独立,避免了系统间的干扰,这使得应用的部署和管理更加高效。此外,Docker不依赖于特定的编程语言、框架或包装系统,增强了其通用性。
小知识:沙盒(Sandbox)
沙盒是一种虚拟化技术,常用于计算机安全领域。它可以让程序在受限环境中运行,如果程序表现出恶意行为,则可以阻止其进一步执行,从而保护系统的安全。
Docker最初由dotCloud公司开发,是基于LXC(Linux Container)构建的高级容器引擎。它的源码托管在GitHub上,采用Go语言编写,并遵循Apache 2.0协议开源。
- GitHub地址:Docker GitHub
小知识:LXC
LXC代表Linux Container,是一种内核虚拟化技术,提供轻量级的虚拟化解决方案,以便隔离进程和资源。LXC通过Linux内核的命名空间(namespace)实现用户实例之间的隔离,通过控制组(cgroup)管理资源分配和调度。
2. Docker容器技术与虚拟机的区别
相同点
- 虚拟化技术:Docker和虚拟机(VM)都是虚拟化技术,用于隔离应用程序和服务,确保它们能够在独立的环境中运行。
不同点
虚拟机技术
- 架构:虚拟机依赖于Hypervisor(虚拟机监控程序),它负责管理物理硬件资源并将其分配给多个虚拟机。每个虚拟机都有自己的操作系统,创建了多个抽象层。
- 资源消耗:由于每个虚拟机都需要完整的操作系统,因此会消耗更多的内存和存储资源。
- 启动时间:虚拟机的启动时间通常较长,可能需要几分钟,取决于操作系统的加载时间。
容器技术
- 架构:Docker容器直接运行在宿主操作系统上,共享内核,而不需要额外的操作系统层。这样减少了抽象层,提高了性能。
- 资源消耗:容器通常更轻巧,仅包含应用及其依赖,资源占用小。
- 启动时间:Docker容器的启动时间仅需几秒钟,极大提高了开发和部署的效率。
Docker相较于虚拟机的优点
- 轻量级与快速:Docker的容器比虚拟机小得多,启动速度快,使得云部署和分发更加高效。
- 开放平台:Docker提供一个开放的平台,方便构建、发布和运行分布式应用程序。
- 操作系统无关性:开发人员无需关注底层使用的具体Linux操作系统。
- 广泛支持:多家知名科技公司(如Google、微软、亚马逊等)均支持Docker。
- 跨平台支持:Docker不仅支持Unix/Linux操作系统,还支持Windows和Mac。
Docker的局限性
- 数据管理:Docker主要用于计算,不直接管理数据存储。日志、数据库等通常保存在容器外部,可以通过外部挂载的方式(如NFS、iSCSI等)进行管理。
- 镜像大小:虽然容器镜像较小,但不适合存储大量数据,推荐将数据存储放在外部解决方案中。
总结
Docker是一个非常高效的虚拟化解决方案,适用于快速开发和部署应用程序,但在数据管理上需要依赖其他工具和技术。
Docker架构图与工作流程
在深入了解Docker之前,参考下面的架构图有助于理解Docker的基本概念和结构。希望大家在学习完Docker后能再次查看这张图,以加深理解。
-
**镜像(Image):**Docker 镜像,就相当于一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统
-
容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等
-
仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像
Docker工作流程
- 启动Docker:首先需要启动Docker守护进程,使其能够管理容器和镜像。
- 下载镜像到本地:从Docker Hub等镜像仓库下载所需的镜像。
- 启动Docker容器实例:基于下载的镜像创建并启动容器实例。
提示:建议大家注册一个Docker Hub账户,这对后续的学习非常重要,没有账号将无法充分利用Docker的功能。
Docker核心技术
- Namespace:实现容器的进程、网络、消息、文件系统和主机名的隔离,使每个容器都能独立运行。
- Cgroup:用于资源的配额和调度,可以限制每个容器使用的CPU、内存等资源。
Docker特性
- 文件系统隔离:每个容器都有独立的根文件系统,互不影响。
- 资源隔离:通过Cgroup实现系统资源的分配,确保不同容器之间的资源隔离。
- 网络隔离:每个容器运行在自己的网络空间中,拥有虚拟接口和IP地址。
- 日志记录:Docker记录每个容器的标准流(stdout/stderr/stdin),方便实时或批量检索。
- 变更管理:容器文件系统的变更可以提交为新的镜像,便于重复使用与部署。
- 交互式Shell:Docker允许分配虚拟终端,方便与容器进行交互。
SSH客户端
WindTerm 是一款 Github 上开源的 SSH 终端工具,到目前为止它已经收获了 16.9K 颗星,它是完全可以比肩 MobaXterm工具的。其支持的系统及功能如下:
1. 系统支持:
- Linux
- macOS
- Windows
2. 功能支持:
- SSH
- Telnet
- Shell
- TCP
- Serial
- SFTP
- Cmd
- PowerShell
- Git
docker安装
参考文章:
10分钟学会Docker的安装和使用_docker安装-CSDN博客
配置阿里云
注册一个阿里云的账号,在阿里云官网的控制台申请个人容器镜服务、并完成基础配置。
点击镜像加速器
根据官网提示的命令进行操作
操作完成后 再次输入 docker run hello-world。如果能正常运行跳出hello,world 说明配置正确。至此个人账号下的阿里云镜像配置完成,从此下载速度可以变快。(没有加速会导致后续有些操作莫名其妙报错、超时、会很头疼)
Docker学习社区
Docker官方文档教程
学习任何技术,官方文档都是最好的资料教程。
- 访问地址:Docker Docs
Docker中文社区
- 访问地址:docker中文社区
Docker入门到实践开源教程(推荐)
Docker常见命令
类别 | 命令 | 说明 |
---|---|---|
进程相关 | systemctl start docker |
启动 Docker 服务 |
systemctl stop docker |
停止 Docker 服务 | |
systemctl restart docker |
重启 Docker 服务 | |
systemctl status docker |
查看 Docker 服务状态 | |
systemctl enable docker |
设置开机启动 Docker 服务 | |
镜像相关 | docker images |
查看本地所有的镜像 |
docker images -q |
查看所有镜像的 ID | |
docker search 镜像名称 |
从网络中查找需要的镜像 | |
docker pull 镜像名称 |
从 Docker 仓库下载镜像到本地 | |
docker rmi 镜像ID |
删除指定本地镜像 | |
docker rmi $(docker images -q) |
删除所有本地镜像 | |
容器相关 | docker ps |
查看正在运行的容器 |
docker ps -a |
查看所有容器 | |
docker run 参数 --name=容器名称 镜像名称 |
创建并启动容器 | |
docker exec -it 容器名称 /bin/bash |
进入容器 | |
docker stop 容器名称 |
停止容器 | |
docker start 容器名称 |
启动容器 | |
docker rm 容器名称 |
删除容器 | |
docker inspect 容器名称 |
查看容器信息 |
Docker容器数据卷
容器数据卷介绍
Docker容器在产生数据时,如果不使用docker commit生成新的镜像,数据会随着容器的删除而消失。为了解决这一问题,Docker引入了数据卷的概念。
数据卷:数据卷是宿主机中的一个目录或文件,当容器目录和数据卷目录绑定后,对方的修改会立即同步
-
一个数据卷可以被多个容器同时挂载
-
一个容器也可以被挂载多个数据卷
数据卷的作用:
-
容器数据持久化
-
外部机器和容器间接通信
-
容器之间数据交换
配置数据卷
创建启动容器时,使用-v参数设置数据卷
XML
docker run ... --v 宿主机目录(文件):容器内目录(文件) ...
docker run -it --name=c1 -v /root(or~)/data:/root/data_container centos:7
注意事项:
- 目录必须是绝对路径
- 如果目录不存在,会自动创建
- 可以挂载多个数据卷
多容器进行数据交换:
-
多个容器挂载同一个数据卷
-
数据卷容器
创建启动c3数据卷容器,使用 --v 参数设置数据卷
XML
docker run --it --name=c3 --v /volume centos:7 /bin/bash
创建启动 c1 c2 容器,使用 ---volumes-from 参数设置数据卷
XML
docker run --it --name=c1 --volumes-from c3 centos:7 /bin/bash
docker run --it --name=c2 --volumes-from c3 centos:7 /bin/bash
应用部署
MySQL
在Docker容器中部署MySQL,通过外部mysql客户端操作MySQL Server
端口映射:
-
容器内的网络服务和外部机器不能直接通信,外部机器和宿主机可以直接通信,宿主机和容器可以直接通信
-
当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射到宿主机的端口上。外部机器访问宿主机的该端口,从而间接访问容器的服务。这种操作称为:端口映射
MySQL部署步骤:搜索mysql镜像,拉取mysql镜像,创建容器,操作容器中的mysql
1、搜索 MySQL 镜像
XML
docker search mysql
2、拉取 MySQL 镜像
选择一个具体版本的 MySQL 镜像进行拉取,这里以 5.6 版本为例:
XML
docker pull mysql:5.6
3、创建容器并设置端口和目录映射
在宿主机上创建一个目录来存储 MySQL 的数据。
XML
mkdir ~/mysql
cd ~/mysql
然后运行以下命令来创建并启动 MySQL 容器:
XML
docker run -id \
-p 3307:3306 \
--name=c_mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.6
参数说明:
- -p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口。
- -v $PWD/conf:/etc/mysql/conf.d:将当前目录下的 conf 目录挂载到容器的 /etc/mysql/conf.d,用于配置文件。
- -v $PWD/logs:/logs:将当前目录下的 logs 目录挂载到容器的 /logs,用于日志存储。
- -v $PWD/data:/var/lib/mysql:将当前目录下的 data 目录挂载到容器的 /var/lib/mysql,用于数据库数据存储。
- -e MYSQL_ROOT_PASSWORD=123456:设置 MySQL root 用户的密码。
4、进入容器并操作 MySQL
XML
docker exec -it c_mysql /bin/bash
进入容器后,可以使用 MySQL 客户端进行数据库操作:
XML
mysql -u root -p
输入上述命令后,系统会提示你输入密码,输入 123456 即可登录。
要退出 MySQL 客户端,可以使用以下命令:
sql
exit;
Tomcat
搜索tomcat镜像
XML
docker search tomcat
拉取tomcat镜像
XML
docker pull tomcat
创建容器,设置端口映射、目录映射
在主机上创建一个目录用于存储 Tomcat 的数据信息:
XML
mkdir ~/tomcat
cd ~/tomcat
使用以下命令创建并运行 Tomcat 容器:
XML
docker run -id --name=c_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
参数说明:
- -id:以分离模式运行容器,并返回容器 ID。
- --name=c_tomcat:给容器命名为 c_tomcat。
- -p 8080:8080:将容器的 8080 端口映射到主机的 8080 端口,以便可以通过 http://localhost:8080 访问。
- -v $PWD:/usr/local/tomcat/webapps:将当前主机目录挂载到容器的 /usr/local/tomcat/webapps,这样可以方便地在主机上管理 web 应用。
访问 Tomcat
在浏览器中输入 http://ip:8080
,你应该可以看到 Tomcat 的默认欢迎页面。
Redis
以下是如何在 Docker 中使用 Redis 的详细步骤。
- 搜索 Redis 镜像
使用以下命令在 Docker Hub 上搜索 Redis 镜像:
XML
docker search redis
- 拉取 Redis 镜像
将指定版本的 Redis 镜像拉取到本地:
XML
docker pull redis:5.0
- 创建容器并设置端口映射
运行 Redis 容器,并将其端口映射到主机:
XML
docker run -id --name=c_redis -p 6379:6379 redis:5.0
- 连接到 Redis
你可以通过 Docker 的 exec 命令进入已经运行的 Redis 容器,使用 Redis CLI 进行操作:
XML
docker exec -it c_redis redis-cli
在 Redis CLI 中,你可以输入 Redis 命令,例如:
XML
SET key "value"
GET key
管理容器
查看正在运行的容器:
XML
docker ps
停止容器:
XML
docker stop 容器命名
启动容器:
XML
docker start 容器命名
删除容器:
XML
docker rm 容器命名
镜像原理
底层原理
Docker 镜像本质是什么? Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G? Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
操作系统的组成部分:进程调度子系统、进程通信子系统、内存管理子系统、设备管理子系统、文件管理子系统、网络通信子系统、作业控制子系统
Linux文件系统由bootfs和rootfs两部分组成:
-
bootfs:包含bootloader(引导加载程序)和 kernel(内核)
-
rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件
-
不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos
Docker镜像原理:
-
Docker镜像是一个分层文件系统,是由特殊的文件系统叠加而成,最底端是 bootfs,并复用宿主机的bootfs ,第二层是 root文件系统rootfs称为base image,然后再往上可以叠加其他的镜像文件
-
统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统
-
一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。
-
当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器
问题:
-
Docker 中一个Ubuntu镜像为什么只有200MB,而一个Ubuntu操作系统的iso文件要几个个G? Ubuntu的iso镜像文件包含bootfs和rootfs,而docker的Ubuntu镜像复用操作系统的bootfs,只有rootfs和其他镜像层
-
Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB? 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB
镜像制作
Dockerfile
基本概述
Dockerfile是一个文本文件,包含一条条的指令,每一条指令构建一层,基于基础镜像最终构建出新的镜像
-
对于开发人员:可以为开发团队提供一个完全一致的开发环境
-
对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了
-
对于运维人员:在部署时,可以实现应用的无缝移植
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
Centos
自定义centos7镜像:
-
默认登录路径为 /usr
-
可以使用vim
实现步骤:
-
定义父镜像:FROM centos:7
-
定义作者信息:MAINTAINER seazean < zhyzhyang@sina.com>
-
执行安装vim命令: RUN yum install -y vim
-
定义默认的工作目录:WORKDIR /usr
-
定义容器启动执行的命令:CMD /bin/bash
-
通过dockerfile构建镜像:docker bulid --f dockerfile文件路径 --t 镜像名称:版本
Boot
定义dockerfile,发布springboot项目:
实现步骤:
-
定义父镜像:FROM java:8
-
定义作者信息:MAINTAINER seazean < zhyzhyang@sina.com>
-
将jar包添加到容器: ADD springboot.jar app.jar
-
定义容器启动执行的命令:CMD java--jar app.jar
-
通过dockerfile构建镜像:docker bulid --f dockerfile文件路径 --t 镜像名称:版本
服务编排
基本介绍
微服务架构的应用系统中一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,维护的工作量会很大。
-
从Dockerfile build image 或者去dockerhub拉取image;
-
创建多个container,管理这些container(启动停止删除)
服务编排:按照一定的业务规则批量管理容器
Docker Compose是一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建,启动和停止。使用步骤:
-
利用 Dockerfile 定义运行环境镜像
-
使用 docker-compose.yml 定义组成应用的各服务
-
运行 docker-compose up 启动应用
虚拟机
容器:
-
容器是将软件打包成标准化单元,以用于开发、交付和部署
-
容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置
-
容器化软件在任何环境中都能够始终如一地运行。
-
容器赋予了软件独立性,使其免受外在环境差异的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突
容器和虚拟机对比:
-
相同:容器和虚拟机具有相似的资源隔离和分配优势
-
不同:
-
容器虚拟化的是操作系统,虚拟机虚拟化的是硬件。
-
传统虚拟机可以运行不同的操作系统,容器只能运行同一类型操作系统
特性 容器 虚拟机 启动 秒级 分钟 硬盘使用 一般为MB 一般为GB 性能 接近原生 弱于原生 系统支持量 单机支持上千个容器 一般几十个 -