一、Docker 的用途#
Docker 的出现让应用环境配置,发布和测试变得更加轻松
比如你写了一个 web 应用,并且本地调试没有任何问题,这时候想要发给朋友看看,或则部署到服务器上
那首先,就需要配置相同的软件与环境,比如数据库,Web 服务器,必要的插件和库等等
而且也不能保证软件一定能够正常的运行
因为用的可能是完全不同的操作系统,即便同样使用的是 Linux,每一个发行版也会有微小的差别
所以,为了完全模拟相同的本地开发环境,自然会想到虚拟机
但是虚拟机需要模拟整个硬件,运行整个操作系统,不但体积臃肿内存占用高,程序性能也会受到影响
这是就需要使用到 Docker
二、Docker 介绍#
Docker 就类似于虚拟机,但却轻量很多
他不会模拟底层的硬件,只会为每个应用提供一个完全隔离的运行环境
可以在环境中配置不同的工具软件,不同环境之间不会受到影响
这个环境在 Docker 中,就称为 Container (容器)
这时候,就不得不提到 Docker 中三个重要的概念
1、Image / 镜像#
可以把镜像理解成一个虚拟机的快照
里面包含了要部署的 应用程序以及它所关联的所有库、软件
通过镜像,可以创建多个不同 Container
2、Container / 容器#
这里的 Container 就像是虚拟机
里面运行了部署上的应用程序
每个 Container 都是 独立运行的,他们之间互不影响
3、Dockerfile#
它主要用来创建 Image 镜像
可以理解成在虚拟机中安装操作系统和运行环境一样
只不过通过 Dockerfile 这个 自动化脚本 完成了
三、Docker 安装#
详见笔记
四、Dockerfile 的配置#
在项目中创建一个 dockerfile 文件
FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
1、首先需要用 FROM 命令指定一个基础镜像 (Base Image)#
在 Docker Hub 上也提供了很多高质量操作系统镜像不同的操作系统提供不同的包管理工具,比如 Ubuntu 上的 apt
还有为某种语言或则某种框架开发的镜像,比如 Python、Nginx、Node、Tomcat 等
FROM Node:Latest
后面跟的是版本或则标签
2、指定 Docker 命令的工作路径 (work directory)#
WORKDIR /app
这个命令指定了,这个命令之后所有的 Docker 命令的工作路径
如果这个路径不存在,Docker 会自动创建,这样可以避免使用绝对路径或则手动 cd 切换路径,增加程序的可读性
3、拷贝程序到 Docker 镜像中#
COPY . .
COPY <本地路径> < 目标路径 >
第一个参数为本地路径, “.” 代表了程序根目录下的所有文件
第二个参数为 Docker 镜像中的路径,而这里的 “.” 代表了当前的工作路径
除了 .dockerignore 排除的路径都会拷贝进去
4、运行命令#
在创建镜像时运行任意的 Shell 命令
因为这里使用的是 node , 所以使用 npm install 来安装这个程序的所有关联
RUN npm install
5、暴露端口#
EXPOSE 3000
将容器的 3000 端口暴露出来,允许外部连接这个端口。
6、Docker 容器运行后执行命令#
最后用 CMD 来指定当 Docker 容器运行起来后要执行的命令
CMD ["npm", "start"]
需要注意这里的 容器 ≠ 镜像
并且和 RUN 不同,RUN 是创建镜像的时候使用的,而 CMD 是运行容器时使用的
到此,就完成了自动化脚本 dockerfile
五、创建镜像#
运行命令 docker build 来创建一个镜像
docker build -t my-blog .
-t 指定了镜像的名字
最后的 . 告诉 docker 应该在当前目录下寻找 dockerfile
第一次执行,会等待稍长时间
因为 Docker 会下载必要的镜像文件,
以后再执行会快很多,因为 Docker 会缓存之前的每一个操作
这个在 Docker 中也被称作 分层 (Layers)
六、启动容器#
有了镜像之后,可以通过 docker run 来启动一个容器
docker run -p 3000:3000 -d my-blog
这里的 -p 他会将容器上的某一个端口,映射到本地主机上
这样才能从主机上访问容器中的 Web 应用
前面的 3000 是本地主机上的端口,后面的 3000 是容器上的端口
后面的 -d 是让容器在后台运行,这样容器的输出就不会直接显示在控制台
这时候打开本地 localhost:3000 就可以访问到
七、Docker Desktop 操作#
在 Docker Desktop 中 看到这个应用在后台的所有输出
Container 面板#
Container面板中,显示了当前运行的所有容器,可以选择 **停止、重启或者删除**
还可以通过 Shell 远程调试这个容器
以下是他们所对应的命令行指令
但是需要注意的是,当删除这个容器时,之前所做的修改、新添加的数据都会全部丢失
就好比删除了虚拟机,里面的数据也会全部销毁
如果需要保留容器中的数据,可以使用 Docker 提供的 volume 数据卷
八、Volume 数据卷#
可以把它当作是一个 **在本地主机和不同容器中共享的文件夹**
比如在某个容器中修改了某一个 volume 的数据,他会同时反应在其他的容器上
1、创建数据卷#
docker volume create my-blog-data
可以通过上面的命令来创建一个数据卷
2、指定数据卷#
在启动容器的时候 通过 -v 参数来指定数据卷
将这个数据卷挂载 (mount) 到容器中的哪一个路径下
docker run -p 3000:3000 -v my-blog-data:/etc/blogData my-blog
这里将 my-blog-data 挂载到了 /etc/blogData 这个路径下
向这个路径写入的任何数据都会被永久保存在这个数据卷中
九、多个容器协作#
在实际使用中,常常会使用到多个容器
比如使用一个容器来运行 Web 应用,另一个容器来运行数据库
这样可以做到数据和应用逻辑的有效分离
当 Web 程序宕机了,数据库依然在有效运转,这时只需要修复 Web 容器即可
而 docker compose 可以做到这一点
十、Docker Compose#
1、创建一个 docker-compose.yml 文件#
version: '3'
services:
web:
build:
ports:
- "3000:3000"
db:
image: "mysql"
environment:
MYSQL_DATABASE: blog
MYSQL_ROOT_PASSWORD: password
volumes:
- my-blog-data:/var/lib/mysql
volumes:
my-blog-data:
在这个文件下,通过 services 来定义多个 container
比如一个 web 容器,运行 web 应用,一个 mysql 容器,运行数据库
在数据库的容器中,可以添加环境变量 数据库名和连接密码
还可以指定一个数据卷,用来 永久存放数据
2、运行 docker compose#
使用 docker compose up -d
命令,运行所有的容器
这里的 -d 同样代表在后台运行所有的容器
3、停止并删除所有容器#
docker compose down
不过新创建的数据卷需要手动在 Docker Desktop 中删除
或者在命令后添加 --volumes
参数
以上的操作也都可以在 Docker Desktop 中完成