简介

Docker是一个用于 构建(build) 运行(run) 传送(share) 应用程序的平台,可以将我们的应用程序打包成一个个的集装箱,然后把它运送到任何需要的地方

有了docker,我们就可以将应用程序和它运行时所需要的各种依赖包,第三方软件库,配置文件等打包在一起,以便在任何环境中都可以正确地运行

为什么要使用Docker:

举个例子,比如我们写了一个网站用到了现在比较流行的前后端分离架构,前端使用Vue框架来构建网站的界面,后端使用Java的SpringBoot微服务框架来提供各种服务和接口,然后使用MySQL数据库来存储数据。如果没有Docker,你可能需要在本地先安装前端NodeJS环境,各种npm依赖包,Java运行时环境和SpringBoot微服务的各种第三方依赖包,MySQL数据库,配置各种环境变量,然后再启动这些服务,网站才能正常运行起来,如果项目规模再大一点,你可能还需要配置Redis缓存,Nginx负载均衡,甚至各种微服务框架等等

而有了Docker,我们就可以将它们打包成一个个的集装箱,只要你在开发环境中运行成功了,那么在其他环境中一定也是可以运行成功的

Docker和虚拟机的区别

虚拟机这是通过一种叫做虚拟化的技术来实现的,虚拟化技术是一种将物理资源虚拟为多个逻辑资源的技术,它可以将一台物理服务器虚拟成多个逻辑服务器,每个逻辑服务器都有自己的操作系统CPU 内存 硬盘和网络接口等等,它们之间是完全隔离的,可以独立运行。虚拟机在一定程度上实现了资源的整合,可以将一台服务器的计算能力,存储能力, 网络资源分配给多个逻辑服务器,实现多台服务器的功能,但是它的缺点也非常明显,每台虚拟机都需要占用大量的资源,启动速度慢,因为他们都是一个完整的系统但我们只要提供服务就行

docker和容器是两个不同的概念,其实Docker只是容器的一种实现,是一个容器化的解决方案和平台,而容器是一种虚拟化技术,和虚拟机类似也是一个独立的环境,可以在这个环境中运行应用程序。和虚拟机不同的是它并不需要在容器中运行一个完整的操作系统,而是使用宿主机的操作系统,所以启动速度非常快,通常只需要几秒钟,同时因为需要的资源更少,所以可以在一台物理服务器上运行更多的容器,这样就可以更加充分地利用服务器的资源,减少资源的闲置和浪费。比如我们一合物理服务器上可能只能运行几个虚拟机,但是却可以运行上百个容器,这就是容器和虚拟机的一些主要区别

基本原理和概念

需要学习几个概念就是Docker中的镜像 容器和仓库。镜像是一个只读的模板,它可以用来创建容器,容器是Docker的运行实例,它提供了一个独立的可移植的环境,可以在这个环境中运行应用程序。

镜像是一个只读的模板,而容器是一个运行实例,镜像和容器的关系就像Java中的类和实例的关系一样,我们可以定义一个类中有哪些属性和方法,这个定义好的类就是一个模板,然后我们可以根据这个模板来创建多个实例,这些实例就是这个类的对象,对应到Docker中镜像就是一个模板,容器就是这个模板的一个实例,可以有一个也可以有多个。

现实中的例子:镜像就像是一个食谱,详细地描述了如何来制作一道美味的菜肴,而容器就是你根据这个食谱做出来的那道菜,你可以根据这个食谱做出很多道菜,但是这些菜都是根据同一个食谱做出来的,只要你严格按照食谱的要求来做,那么做出来的菜就是一样的。而且你也可以把这个食谱分享给其他同样喜欢美食的朋友,食谱如何分享给别人呢,这就涉及到我们刚刚提到的第三个概念仓库

Docker仓库是用来存储Docker镜像的地方,最流行和最常用的仓库就是Dockerhub,它是一个公共的Docker仓库,用来集中存储和管理Docker镜像,我们可以在这里下载各种镜像,也可以将自己的镜像上传到这里,这样就可以实现镜像的共享和复用,这也是Docker非常流行的一个重要原因

安装配置

下载安装包后如果是win10可以通过cmd输入改变安装位置

1
"Docker Desktop Installer.exe" install --installation-dir="D:\Docker"

然后启动终端在命令行输入,会看到docker的版本信息

1
docker version

可以看到client和server,如果只看到client说明docker没有启动

Docker的体系结构:Docker是使用client-Server架构模式,Docker client 和 Docker Daemon 之间通过 Socket 或者 RESTfuLAPI 进行通信。Docker Daemon就是服务端的守护进程,他负责管理Docker的各种资源,Docker client负责同Docker Daemon发送请求,Docker Daemon接收到请求之后进行处理,然后将结果返回给Docker client。

这里的 Docker Daemon 是一个后台进程,用来接收并处理来自Docker客户端的请求,然后将结果返回给客户端,所以我们在终端中输入的各种Docker命令,实际上都是通过Docker客户端发送给Docker Daemon的,然后Docker Deamon再进行处理,最后再将结果返回给客户端,然后就可以在终端中看到执行结果了

image-20251016012805365

容器化和dockerfile

容器化顾名思义就是将应用程序打包成容器,然后在容器中运行应用程序的过程,这个过程简单来说可以分成三个步骤

  1. 首先需要创建一个Dockerfile,来告诉Docker构建应用程序镜像所需要的步骤和配置
  2. 然后使用Dockerfile来构建镜像
  3. 接下来我们就可以使用这个镜像来创建和运行容器

这里出现了一个新的概念Dockerfile,Dockerfile是一个文本文件,里面包含了一条条的指令,用来告诉Docker如何来构建镜像,这个镜像中包括了我们应用程序执行的所有命令,也就是我们刚刚提到的各种依赖 配置环境和运行应用程序所需要的所有内容,一般包括精简版的操作系统,应用程序的运行时环境,应用程序,比如jar包,应用程序的第三方依赖库或者包,应用程序的配置文件 环境变量等等,一般来说我们会在项目的根目录下创建一个叫Dockerfile的文件,第一个字母D大写 其他都小写,在这个文件中写入构建镜像所需要的各种指令之后,Docker就会根据这个Dockerfile文件构建镜像,有了镜像之后我们就可以使用这个镜像来创建容器,然后在容器中运行应用程序

实践

可以把这些命令写到dockerfile中,剩下的工作就可以交给docker自动完成

  1. Step1:安装操作系统
  2. Step2: 安装JavaScript运行环境(NodejS)
  3. Step3: 复制应用程序、依赖包、配置文件
  4. Step4: 执行启动命令运行程序

我们在项目的根目录下再创建一个叫做Dockerfile的文件,注意 这个文件的命名是Dockerfile,没有任何扩展名,第一个字母D大写其他都小写,如果没有安装docker就可以在扩展里搜docker然后安装

在这个Dockerfile我们需要先指定一个基础镜像,镜像是按层次结构来构建的,每一层都是基于上一层的,所以我们需要先指定一个基础镜像,然后在这个镜像的基础上添加我们的应用程序。

我们可以从一个最基础的Linux镜像开始,然后在这个镜像基础上安装Node]s和我们的应用程序,或者 我们也可以直接使用NodeJs的镜像,因为这个镜像已经是基于Linux来构建的了,所以直接拿来使用就可以了。node后面的14表示NodeJs的版本,这里我们使用的是14版本,再后面中杠后面的Alpine表示的是这个镜像是基于Alpine这个Linux发行版来构建的。Alpine和其他我们经常听说的RedHat CentOs 一样,都是一种Linux发行版,只不过它是一个非常轻量级的Linux发行版,体积非常小,只有几十m,所以下载和部署都非常的快。

1
FROM node:14-alpine

配置完运行环境之后还需要把我们的应用程序复制到镜像中,可以使用COPY命令来复制文件,COPY命令后面可以加上两个参数,第一个参数表示源路径,第二个参数表示目标路径。这里的源路径是指相对于Dockerfile文件的路径,目标路径是相对于镜像的路径,那现在我们需要把index.js这个文件复制到镜像的根目录下,就可以执行 COPY index.js,后面加上根目录就可以了。

1
COPY index.js /index.js

然后我们需要在镜像中运行应用程序,可以使用CMD命令来运行应用程序,CMD命令后面可以加上一对方括号,方括号里面的第一个参数表示可执行程序的名字,第二个参数以后表示这个可执行程序接收到的参数,或者也可以使用第二行的格式

1
2
CMD ["node","/index.js"]
CMD node /index.js

到这里就编写完成了,保存一下

1
docker build -t hello-docker .

hello-docker是镜像的名字,点 是当前目录也就是Dockerfile所在的目录,然后我们来执行一下,在一些回显之后镜像构建完成。可以使用下面查看所有的镜像

1
docker image ls

image-20251016223640441

这里你就会看到刚刚构建的镜像,它的名字是hello-docker,这里的latest表示的是镜像的标签,也就是镜像的版本。如果不指定版本那默认就是latest,如果想指定版本,那么就可以在镜像名字后面加上冒号和版本号,这样我们就完成了镜像的构建,使用 下面这个就可以运行

1
docker run hello-docker

如果想在另一个系统运行这个程序,那么就只需要把这个镜像文件复制过去,然后执行一下刚刚的命令就可以了,也可以把这个镜像文件上传到DockerHub或者 Harbor 镜像仓库中,然后任何人都可以在任何地方,使用 docker pull 命令来下载这个镜像文件,然后运行这个应用程序

我们在一个网站中运行这个镜像,这个网站叫做 Play With Docker,它是一个非常好用的在线 Docker 环境,你可以在这里免费兴试使用Docker的各种功能,比如构建镜像 运行容器等等。点击一下左上角这个小扳手的设置按钮,然后选择最下面的选项,就可以进入到这个虚拟机的控制台界面了

image-20251016234349995

这个屏幕没有全屏字体也有点小, 那我们再来点一下左上角的设置按钮,它提示我们可以使用Alt加上回车键,使用Command和加号键来放大字体。调整完然后在终端中输入 docker pull,后面加上DockerHub上镜像的地址,这里斜杠前面表示用户名后面表示镜像的名称

1
2
docker pull geekhour/hello-docker
docker images

执行完后我们再来输入 docker images来查看一下镜像列表,就可以看到我们刚刚下载的这个镜像了,然后我们使用 docker run 命令来启动一下就启动了

docker desktop使用

Docker Desktop 封装了容器日常使用和管理的各种常用功能,打开控制台面板之后在左上角菜单中就会看到容器和镜像,点一下镜像按钮就可以看到我们刚刚构建的镜像了,在这里可以找到镜像的名称 标签 状态 创建时间 大小等信息,后面还有一个播放按钮,点击就可以直接使用这个镜像来运行一个容器了。在后面的三个小点表示的是更多操作,点击之后会展开一个弹出菜单,image-20251017000422874

第一项是查看这个镜像包中的详细信息,第三项和第四项就是镜像的远程仓库相关的操作,也就是从远程仓库拉取镜像,或者把这个镜像推送到远程仓库中,当然前提是你需要先点击一下右上角的头像这个位置来登录到远程仓库中

我们再来看一下容器,和镜像操作差不多,容器和镜像下面还有一个Volumes的菜单,这个是逻辑卷的意思,我们可以在这里查看容器中的逻辑卷,逻辑卷是Docker中用来存储数据的,Docker容器有一个特点就是容器中的数据是不会持久化的,当我们创建一个容器的时候,它通常以一个干净的文件系统开始,容器启动之后我们可以在容器中创建文件 修改文件,但是当容器停止之后容器中的所有数据都会丢失掉,如果我们想要持久化容器中的数据的话,逻辑卷就是用来解决这个问题的,它可以把容器中的目录或者指定路径映射到宿主机的某一个目录或者位置上,这样就可以将数据保存到宿主机的磁盘上,实现了数据的持久化

再往下面是一个Beta版的测试功能,是用来管理开发环境的,可以在这里创建一个开发环境,然后使用一些代码来配置这个开发环境,这样就可以把这个开发环境共享给项目中的其他开发人员,让每个人都在一个相同的环境下进行开发,避免因为环境的不一致导致的各种问题

image-20251017002424657

下面一个菜单是官方提供的学习中心

最后还提供了一个添加扩展的功能,可以在这里安装一些扩展来增强它的功能

docker compose

Docker Compose 是由Docker官方开源的项目,是一个用来定义和运行多个Docker容器应用程序的工具,比如如果想要搭建一个网站的话,可能会使用到前端 后端 数据库,甚至缓存 负载均衡等多个服务器,这些服务都是独立的,但是它们之间又是有关联的,需要相互配合来工作,这些服务之间的关联关系,就是Docker compose要解决的问题,它通过一个单独的docker-compose.yaml的配置文件,来将这一组互相关联的容器组合在一起形成一个项目,然后使用一条命令就可以启动 停止或者重建这些服务,这样就可以非常方便的管理这些服务了

1
$ docker compose up

举例:如果你的项目组中来了一个新同事,之前他可能需要半天时间去安装各种依赖和配置运行环境,现在有了Docker Compose之后只需要执行一下docker compose up 命令,就可以自动安装各种依赖和配置运行环境然后运行。