什么是Docker及其工作原理
- 虚拟化技术
- Docker是什么?
- 三大基本术语
- 核心算法原理和具体操作步骤
- Docker和传统虚拟化技术区别
- 为什么使用Docker?
- Docker有什么作用?
- 1.解决应用部署的环境问题
- 遇到问题
- 达到效果
- 2.容器化
- docker的各种命令解释
- 运行机制
- docker pull 执行过程
- docker run 执行过程:
- 基本命令
- 命令词介绍
- 管理命令
- 命令
- 镜像有关操作
- 容器有关操作
- 命令词介绍
- 数据卷相关操作
- Dockerfile文件命令概括解释
- Dockerfile命令例子
- FROM-初始化一个新的构建阶段,并为后续指令设置基础镜像
- WORKDIR-设置工作目录
- COPY-用于从 docker 主机复制新文件或者目录至创建的新镜像指定路径中
- ADD-用于将本地文件、目录、或远程文件 URL 添加到镜像中。
- RUN-在镜像构建过程中执行命令。它可以执行任何有效的 shell 命令、可执行文件或脚本
- ENV-定义环境变量
- EXPOSE-声明容器运行时要监听的端口
- CMD-配置容器启动时执行的命令
- ENTRYPOINT-配置容器启动时执行的命令
- 生成镜像
- 运行镜像
- 优化方案
- docker部署Vue项目
- 服务器中创建工作目录
- 构建vue应用镜像
- 编写 nginx config
- 编写Dockerfile
- 执行如下命令
虚拟化技术
虚拟化技术是现代计算机领域的一个重要发展方向,它可以让我们在同一台物理机上运行多个操作系统的实例,提高资源利用率和系统安全性。传统的虚拟化技术主要包括全虚拟化、半虚拟化和容器化等不同的方法
- 全虚拟化:全虚拟化技术允许多个操作系统实例同时运行在同一台物理机上,每个实例都有自己的虚拟硬件资源。这种方法需要模拟整个操作系统,因此资源消耗较大。
- 半虚拟化:半虚拟化技术允许多个操作系统实例同时运行在同一台物理机上,但它们共享部分硬件资源。这种方法相对于全虚拟化来说资源消耗较小。
- 容器化:容器化技术与Docker类似,它将应用程序和其所需的依赖项打包成一个独立的容器,可以在任何支持容器化技术的环境中运行
Docker是什么?
docker官网入口
- Docker是一种新兴的容器化技术,它基于操作系统的特性,将应用程序和其所需的依赖项打包成一个独立的容器,可以在任何支持Docker的环境中运行。
Docker的思想来自于 集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走
三大基本术语
- 镜像:理解为软件安装包,可以方便的进行传播和安装,它包含了运行应用程序所需的所有元素,包括代码、运行时环境、库、环境变量和配置文件。
镜像可以通过Dockerfile来进行创建
Dockerfile就相当于一个脚本,编写一些命令,他会识别这些命令并且执行 - 容器:软件安装后的状态,每个软件运行的环境都是独立的、隔离的,称之为容器。
- 仓库:仓库是存放 Docker 镜像的地方。仓库允许你分享你的镜像,你可以将你的镜像推送(push)到仓库,也可以从仓库拉取(pull)其他人分享的镜像。
Docker 提供了一个公共的仓库 Docker Hub,你可以在上面上传你的镜像,或者寻找你需要的镜像。
核心算法原理和具体操作步骤
Docker的核心算法原理是基于操作系统的特性,它使用一种名为cgroups(控制组)和namespace(命名空间)的技术来实现容器化。cgroups用于限制和隔离容器的资源使用,而namespace用于隔离容器的文件系统、进程空间和网络空间。
具体操作步骤如下:
- 创建一个Docker镜像,镜像包含应用程序和其所需的依赖项。
- 从镜像创建一个容器,容器包含应用程序和依赖项的实例。
- 使用cgroups和namespace技术来限制和隔离容器的资源使用和空间。
- 启动容器,容器可以在任何支持Docker的环境中运行。
Docker和传统虚拟化技术区别
Docker | 传统虚拟化技术 | |
---|---|---|
架构差异 | 使用容器引擎,共享主机操作系统的内核 | 每个虚拟机有独立的操作系统 |
资源利用率 | 更快启动速度,占用更少资源 | 启动和资源消耗较大 |
部署和扩展 | 快速部署和启动,容器镜像可复制和共享 | 部署和启动相对耗时 |
隔离性 | 隔离性较传统虚拟化技术稍差 | 提供较强的隔离性 |
应用场景 | 构建和部署分布式应用、微服务架构 | 运行需要完全隔离的应用程序 |
操作系统 | 主要支持LinuX | 几乎所有(KVM) |
内核的使用 | 共享内核 | 独立内核 |
启动速度 | 秒级(相当于启动一个进程) | 分钟级(启动操作系统) |
系统支持量(单机) | 上千个 | 几十个 |
为什么使用Docker?
Docker 的出现主要是为了解决以下问题:“在我的机器上运行正常,但为什么到你的机器上就运行不正常了?
平常开发的时候,项目在本地跑的好好的,但是其他人想要在他的电脑上去跑你的应用程序,但是却跑不起来,他得配置数据库,Web 服务器,插件啥的,非常不方便。Docker的出现解决了这些问题
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了
- 对于运维人员:在部署时,可以实现应用的无缝跨平台移植
Docker有什么作用?
1.解决应用部署的环境问题
快速部署和启动、跨平台和可移植性
遇到问题
大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题:
- 依赖关系复杂,容易出现兼容性问题
- 开发、测试、生产环境有差异
- 例如:微服务的拆分通用给部署带来了很大的麻烦。
分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。
在数百上千台服务中重复部署,环境不一定一致,会遇到各种问题
达到效果
- 可以在不同的操作系统和硬件平台上运行,提供了很高的可移植性。开发人员可以在本地开发容器,并将其部署到任何支持 Docker 的环境中,无需担心环境差异导致的问题
- 可以快速启动、停止和重启,使得应用程序的部署和调试变得非常高效。开发人员可以使用 Docker 定义应用程序的运行时环境,并将其打包成镜像,然后在任何支持 Docker 的主机上快速部署和启动
- 提供了一种描述应用程序运行环境的标准化方式。通过使用 Docker 镜像,开发人员可以明确定义应用程序的依赖项和配置,确保在不同的环境中具有相同的运行环境,从而实现环境一致性
2.容器化
- 使用容器技术将应用程序及其所有依赖关系打包到一个独立的运行环境中,形成一个可移植的容器。容器化使得应用程序在不同的环境中具备一致的运行行为,并且可以快速部署和扩展
docker的各种命令解释
运行机制
docker pull 执行过程
- 客户端将指令发送给docker daemon
- docker daemon 先检查本地images中有没有相关的镜像
- 如果本地没有相关的镜像,则向镜像服务器请求,将远程镜像下载到本地
docker run 执行过程:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系(简版linux系统),并在只读的镜像层外面挂载一层可读写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
基本命令
- docker 帮助命令:docker --help
- 查看系统内核:uname -r
- 启动docker :systemctl start docker
- 查看docker版本: docker verison
- 显示docker系统的信息:docker info
命令词介绍
管理命令
含义 | |
---|---|
container | 管理容器 |
image | 管理镜像 |
network | 管理网络 |
命令
含义 | |
---|---|
attach | 介入到一个正在运行的容器 |
build | 根据 Dockerfile 构建一个镜像 |
commit | 根据容器的更改创建一个新的镜像 |
cp | 在本地文件系统与容器中复制 文件/文件夹 |
create | 创建一个新容器 |
exec | 在容器中执行一条命令 |
images | 列出镜像 |
kill | 杀死一个或多个正在运行的容器 |
logs | 取得容器的日志 |
pause | 暂停一个或多个容器的所有进程 |
ps | 列出所有容器 |
pull | 拉取一个镜像或仓库到 registry |
push | 推送一个镜像或仓库到 registry |
rename | 重命名一个容器 |
restart | 重新启动一个或多个容器 |
rm | 删除一个或多个容器 |
rmi | 删除一个或多个镜像 |
run | 在一个新的容器中执行一条命令 |
search | 在 Docker Hub 中搜索镜像 |
start | 启动一个或多个已经停止运行的容器 |
stats | 显示一个容器的实时资源占用 |
stop | 停止一个或多个正在运行的容器 |
tag | 为镜像创建一个新的标签 |
top | 显示一个容器内的所有进程 |
unpause | 恢复一个或多个容器内所有被暂停的进程 |
镜像有关操作
- 拉取镜像 如nginx: docker pull image-name
- 检索image : docker search image-name
- 列出镜像列表:docker images
- 显示一个镜像历史:docker history image-name
- 保存镜像(将已有镜像导出):docker save -o [保存的目标文件名称] [镜像名称]
- 加载镜像:docker load -i [已保存的镜像包] 如:docker load -i nginx.tar
- 删除镜像:docker rmi [镜像名称]
- 通过容器创建镜像:
- 从已经创建的容器中更新镜像,并且提交这个镜像
使用 Dockerfile 指令来创建一个新的镜像 下面通过已存在的容器创建一个新的镜像。
docker commit -m=“First Image” -a=“ll” 7a15f99695c0 keke/unbantu:17.10.0
docker commit -m=“[描述信息]” -a=“指定镜像作者” [容器id] [创建的目标镜像名]
- 从已经创建的容器中更新镜像,并且提交这个镜像
容器有关操作
- 列出当前所有正在运行的container : docker ps
- 列出所有 container(包括已停止的) : docker ps -a
- 列出最近一次启动的 container : docker ps -l
- 创建并运行一个容器(nginx为例):docker run --name containerName -p 80:80 -d nginx
- 让运行的容器暂停:docker pause [容器名]/ID
- 让运行容器从暂停恢复:docker unpause [容器名]/ID
- 停止运行的容器:docker stop [容器名]/ID
- 让一个停止的容器重新运行:docker start [容器名]/ID
- 删除所有容器: docker rm
docker ps -a -q
- 强制删除正在运行的容器(使用SIGKILL): docker rm -f
- 删除指定容器 :docker rm -l
- 删除与容器有关的数据卷:docker rm -v
- 从一个容器中取日志,参数:-f, --follow=false Follow log output; -t, --timestamps=false Show timestamps 命令: docker logs [容器名]/ID - 列出一个容器里面被改变的文件或者目录,list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的:docker diff Name/ID
- 显示一个运行的容器里面的进程信息:docker top Name/ID
- 从容器里面拷贝文件/目录到本地一个路径: docker cp Name:/container-path to-path
docker cp ID:/container-path to-path
命令词介绍
含义 | |
---|---|
docker run | 创建并运行一个容器 |
–name | 给容器起一个名字,比如叫做ll |
-p | 将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口 |
-d | 后台运行容器 |
nginx | 镜像名称,例如nginx |
docker exec | 进入容器内部,执行一个命令 |
-it | 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互 |
mn | 要进入的容器的名称 |
bash | 进入容器后执行的命令,bash是一个linux终端交互命令 |
数据卷相关操作
- 创建一个数据卷:docker volume create [数据卷名]
- 显示一个或多个volume信息:docker volume inspect [数据卷名]
- 列出所有volume:docker volume ls
- 删除未使用的volume : docker volume prune
- 删除一个或多个volume : docker volume rm [数据卷名]
- 创建容器并挂载数据卷:docker run --name [容器名] -v [需要挂载的数据卷名]😕[容器内目录] -p [宿主机端口]:[容器端口] [镜像名] 。对应容器内目录需要去DockerHub找
例如nginx : docker run --name nginx -v html:/usr/share/nginx/html -p 8080:80 nginx
参考文章
Dockerfile文件命令概括解释
含义 | |
---|---|
FROM | 指定基础镜像 |
RUN | 在镜像构建过程中执行命令 |
COPY | 将文件或目录从构建环境复制到镜像中 |
ADD | 类似于 COPY,但更强大,支持 URL 和解压缩操作 |
WORKDIR | 设置工作目录 |
ENV | 设置环境变量 |
ARG | 定义构建时的参数 |
EXPOSE | 声明容器运行时要监听的端口 |
VOLUME | 创建挂载点,用于持久化数据 |
CMD | 指定容器启动时要运行的默认命令 |
ENTRYPOINT | 配置容器启动时执行的命令 |
LABEL | 添加元数据,用于标记镜像 |
USER | 设置容器中运行命令的用户 |
SHELL | 配置 shell 类型 |
Dockerfile命令例子
FROM-初始化一个新的构建阶段,并为后续指令设置基础镜像
FROM [--platform=<platform>] <image> [AS <name>]
- platform: 构建的 cpu 架构,如 Linux/amd 64,Linux/arm 64。
- image: 指定 base image 的名称。
- AS name: 指定构建步骤的名称
FROM node:16-alpine as build-stage
WORKDIR-设置工作目录
WORKDIR <directory>
- directory 是要设置为工作目录的路径。可以使用绝对路径或相对路径。如果指定的路径不存在,WORKDIR 指令将创建该目录
WORKDIR /app
COPY-用于从 docker 主机复制新文件或者目录至创建的新镜像指定路径中
COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
# 或
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
- src 是构建环境中要复制的文件或目录的路径。
- dest 是要将文件或目录复制到容器中的目标路径。
COPY package*.json ./
//复制package.json和package-lock.json(如果存在)
//用 docker 缓存层,先把 package 移进去安装依赖,再把剩余文件复制进去,能最大限度利用到缓存来安装依赖,只要 package 不变则安装依赖很快。这是一个很巧妙的优化点
ADD-用于将本地文件、目录、或远程文件 URL 添加到镜像中。
- 它类似于 COPY 指令,但具有更多的功能,比如会它可以解压和下载类似于 COPY 指令,但具有更多的功能,比如会它可以解压和下载
ADD <source> <destination>
- source 是要添加到镜像中的文件、目录或 URL
- destination是文件系统中的目标路径
RUN-在镜像构建过程中执行命令。它可以执行任何有效的 shell 命令、可执行文件或脚本
RUN <command> && <command> ……
- command 是要执行的命令。在 Dockerfile 中可以是任何合法的 shell 命令,例如安装软件包、运行脚本、创建目录等
//安装项目生产依赖
RUN npm install --only=production
// 构建应用
RUN npm run build
ENV-定义环境变量
ENV <key1>=<value1> <key2>=<value2> ...
- key是环境变量的名称
- value 是环境变量的值。这种格式用于设置单个环境变量,也可以使用通配符
ENV MYROOTDIR=/data/web/html/
EXPOSE-声明容器运行时要监听的端口
EXPOSE <port> [<port>/<protocol>...]
- port是要暴露的端口号
- protocol> 是要使用的网络协议,通常是 tcp 或 udp。如果未指定协议,则默认为 tcp
CMD-配置容器启动时执行的命令
CMD ["nginx", "-g", "daemon off;"]
//启动Nginx服务器
- CMD 是 Dockerfile 中的一条指令,用于设置容器启动时默认执行的命令。它定义了容器启动时执行的主要命令,但是可以被 Docker 命令行中的 docker run 中的参数覆盖
ENTRYPOINT-配置容器启动时执行的命令
ENTRYPOINT nginx -g 'daemon off;'
- 类似于 CMD 指令,但ENTRYPOINT 指令设置的命令不会被 Docker 命令行中的 docker run 中的命令覆盖,而是会作为容器的主要命令执行
生成镜像
docker build -t test:v1 .
- 这里的 -t 参数用于给镜像命名
- /. 表示 Dockerfile 所在的当前目录。
运行镜像
docker run -d -p 8088:80 --name test-hello test:v1
//跑在8080端口将test:v1命名为text-hello
- -d 表示在后台运行容器
- -p 8088:80 表示将宿主机的 8088 端口映射到容器的 80 端口。
之后就可以发布到上面说的仓库里面
优化方案
- 优化指令顺序:将不经常变化的指令放在 Dockerfile 的前面,这样可以利用 Docker 的层缓存,加速后续构建过程
# 先复制不经常变动的文件
COPY requirements.txt /app/
# 再复制经常变动的文件
COPY . /app
- 合并命令行:通过使用逻辑运算符 (&&) 合并命令行,减少镜像层的数量。
# 不推荐
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2
# 推荐
RUN apt-get update && \
apt-get install -y package1 package2 && \
rm -rf /var/lib/apt/lists/*
- 使用多阶段构建
如果应用程序有多个构建阶段,可以使用多个FROM指令构建多个阶段的镜像,以减小最终镜像的大小
docker部署Vue项目
服务器中创建工作目录
- 前端打包好dist文件
构建vue应用镜像
- nginx 是一个高性能的HTTP和反向代理服务器,此处我们选用 nginx 镜像作为基础来构建我们的vue应用镜像
docker pull nginx
编写 nginx config
server {
listen 80;
server_name localhost; # 修改为docker服务宿主机的ip
location /api/ { ##前端接口所有的/api开头的接口都会被这里代理到下方proxy_pass的地址中
proxy_pass http://192.168.1.3:9000/api/; #转发后端请求的地址,前后端分离基本都会用到
proxy_connect_timeout 6000; #链接超时设置
proxy_read_timeout 6000; #访问接口超时设置
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
编写Dockerfile
FROM nginx:该镜像是基于nginx:latest镜像构建的
MAINTAINER onesummer:添加说明
RUN rm /etc/nginx/conf.d/default.conf:删除目录下的default.conf文件
ADD default.conf /etc/nginx/conf.d/:将default.conf复制到/etc/nginx/conf.d/下,用本地的default.conf配置来替换nginx镜像里的默认配置
COPY dist/ /usr/share/nginx/html/:将项目根目录下dist文件夹(构建之后才会生成)下的所有文件复制到镜像/usr/share/nginx/html/目录下
执行如下命令
# 生成镜像
docker build -t [镜像名称] .
//-t 后输入给镜像取的名称,最后的点 (.) 不要忘记,代表给利用当前 dockerfile 构建镜像。 在镜像名称后要空格,再加一点
# 启动
docker run -d -p 88:80 --name [容器名] [镜像名]
- 我们现在在浏览器中输入IP+端口号,就可以显示出网页。上图中的端口号是88。88是映射出服务器的端口号,可以自行修改。