当前位置: 首页 > news >正文

Docker详解

Docker是做什么的? 

Docker 可以帮助我们下载应用镜像,创建并运行镜像的容器,从而快速部署应用

什么是镜像?

将应用所需的函数库、依赖、配置等与应用一起打包得到的就是镜像 

什么是容器?

为每个镜像的应用进程创建的隔离运行环境就是容器 

什么是镜像仓库? 

存储和管理镜像的服务就是镜像仓库,
DockerHub 是目前最大的镜像仓库,其中包含各种常见的应用镜像

常见命令: 

  • docker run:创建并运行一个容器,-d是让容器在后台运行
  • --name mysql:给容器起一个名字
  • -p 3306:设置端口映射
  • -e KEY=VALUE:是设置环境变量
  • mysql:运行的镜像的名字

其中,比较常见的命令有:

命令

说明

文档地址

docker pull

拉取镜像

docker pull

docker push

推送镜像到DockerRegistry

docker push

docker images

查看本地镜像

docker images

docker rmi

删除本地镜像

docker rmi

docker run

创建并运行容器(不能重复创建)

docker run

docker stop

停止指定容器

docker stop

docker start

启动指定容器

docker start

docker restart

重新启动容器

docker restart

docker rm

删除指定容器

docs.docker.com

docker ps

查看容器

docker ps

docker logs

查看容器运行日志

docker logs

docker exec

进入容器

docker exec

docker save

保存镜像到本地压缩文件

docker save

docker load

加载本地压缩文件到镜像

docker load

docker inspect

查看容器详细信息

docker inspect

 2、数据卷

容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。大家思考几个问题:

  • 如果要升级MySQL版本,需要销毁旧容器,那么数据岂不是跟着被销毁了?

  • MySQL、Nginx容器运行后,如果我要修改其中的某些配置该怎么办?

  • 我想要让Nginx代理我的静态资源怎么办?

因此,容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦。 

2.1、什么是数据卷

数据卷(volume)是一个虚拟目录,是容器内目录宿主机目录之间映射的桥梁。

以Nginx为例,我们知道Nginx中有两个关键的目录:

  • html:放置一些静态资源

  • conf:放置配置文件

如果我们要让Nginx代理我们的静态资源,最好是放到html目录;如果我们要修改Nginx的配置,最好是找到conf下的nginx.conf文件。

但遗憾的是,容器运行的Nginx所有的文件都在容器内部。所以我们必须利用数据卷将两个目录与宿主机目录关联,方便我们操作。如图:

暂时无法在飞书文档外展示此内容

在上图中:

  • 我们创建了两个数据卷:confhtml

  • Nginx容器内部的conf目录和html目录分别与两个数据卷关联。

  • 而数据卷conf和html分别指向了宿主机的/var/lib/docker/volumes/conf/_data目录和/var/lib/docker/volumes/html/_data目录

这样以来,容器内的confhtml目录就 与宿主机的confhtml目录关联起来,我们称为挂载。此时,我们操作宿主机的/var/lib/docker/volumes/html/_data就是在操作容器内的/usr/share/nginx/html/_data目录。只要我们将静态资源放入宿主机对应目录,就可以被Nginx代理了。

/var/lib/docker/volumes这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data

为什么不让容器目录直接指向宿主机目录呢

  • 因为直接指向宿主机目录就与宿主机强耦合了,如果切换了环境,宿主机目录就可能发生改变了。由于容器一旦创建,目录挂载就无法修改,这样容器就无法正常工作了。

  • 但是容器指向数据卷,一个逻辑名称,而数据卷再指向宿主机目录,就不存在强耦合。如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可。

数据卷的相关命令有:

命令

说明

文档地址

docker volume create

创建数据卷

docker volume create

docker volume ls

查看所有数据卷

docs.docker.com

docker volume rm

删除指定数据卷

docs.docker.com

docker volume inspect

查看某个数据卷的详情

docs.docker.com

docker volume prune

清除数据卷

docker volume prune

 注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建

3.镜像

前面我们一直在使用别人准备好的镜像,那如果我要部署一个Java项目,把它打包为一个镜像该怎么做呢?

2.3.1.镜像结构

要想自己构建镜像,必须先了解镜像的结构。

之前我们说过,镜像之所以能让我们快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。

因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。

举个例子,我们要从0部署一个Java应用,大概流程是这样:

  • 准备一个linux服务(CentOS或者Ubuntu均可)

  • 安装并配置JDK

  • 上传Jar包

  • 运行jar包

那因此,我们打包镜像也是分成这么几步:

  • 准备Linux运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)

  • 安装并配置JDK

  • 拷贝jar包

  • 配置启动脚本

上述步骤中的每一次操作其实都是在生产一些文件(系统运行环境、函数库、配置最终都是磁盘文件),所以镜像就是一堆文件的集合

但需要注意的是,镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer)。这样,如果我们构建时用到的某些层其他人已经制作过,就可以直接拷贝使用这些层,而不用重复制作。

例如,第一步中需要的Linux运行环境,通用性就很强,所以Docker官方就制作了这样的只包含Linux运行环境的镜像。我们在制作java镜像时,就无需重复制作,直接使用Docker官方提供的CentOS或Ubuntu镜像作为基础镜像。然后再搭建其它层即可,这样逐层搭建,最终整个Java项目的镜像结构如图所示:

 

4.Dockerfile

由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。

而这种记录镜像结构的文件就称为Dockerfile,其对应的语法可以参考官方文档:

https://docs.docker.com/engine/reference/builder/

其中的语法比较多,比较常用的有:

指令

说明

示例

FROM

指定基础镜像

FROM centos:6

ENV

设置环境变量,可在后面指令使用

ENV key value

COPY

拷贝本地文件到镜像的指定目录

COPY ./xx.jar /tmp/app.jar

RUN

执行Linux的shell命令,一般是安装过程的命令

RUN yum install gcc

EXPOSE

指定容器运行时监听的端口,是给镜像使用者看的

EXPOSE 8080

ENTRYPOINT

镜像中应用的启动命令,容器运行时调用

ENTRYPOINT java -jar xx.jar

例如,要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]

同学们思考一下:以后我们会有很多很多java项目需要打包为镜像,他们都需要Linux系统环境、JDK环境这两层,只有上面的3层不同(因为jar包不同)。如果每次制作java镜像都重复制作前两层镜像,是不是很麻烦。

所以,就有人提供了基础的系统加JDK环境,我们在此基础上制作java镜像,就可以省去JDK的配置了:

# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]

是不是简单多了

4.构建镜像

当Dockerfile文件写好以后,就可以利用命令来构建镜像了。

准备好了一个demo项目及对应的Dockerfile:

首先,我们将课前资料提供的docker-demo.jar包以及Dockerfile拷贝到虚拟机的/root/demo目录:

然后,执行命令,构建镜像:

# 进入镜像目录
cd /root/demo
# 开始构建
docker build -t docker-demo:1.0 .

命令说明:

  • docker build : 就是构建一个docker镜像

  • -t docker-demo:1.0-t参数是指定镜像的名称(repositorytag

  • . : 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.代表当前目录,也可以直接指定Dockerfile目录:

# 直接指定Dockerfile目录
docker build -t docker-demo:1.0 /root/demo

结果:

查看镜像列表:

# 查看镜像列表:
docker images
# 结果
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
docker-demo   1.0       d6ab0b9e64b9   27 minutes ago   327MB
nginx         latest    605c77e624dd   16 months ago    141MB
mysql         latest    3218b38490ce   17 months ago    516MB

然后尝试运行该镜像:

# 1.创建并运行容器
docker run -d --name dd -p 8080:8080 docker-demo:1.0
# 2.查看容器
dps
# 结果
CONTAINER ID   IMAGE             PORTS                                                  STATUS         NAMES
78a000447b49   docker-demo:1.0   0.0.0.0:8080->8080/tcp, :::8090->8090/tcp              Up 2 seconds   dd
f63cfead8502   mysql             0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   Up 2 hours     mysql

# 3.访问
curl localhost:8080/hello/count
# 结果:
<h5>欢迎访问商城, 这是您第1次访问<h5>

相关文章:

  • 贪心算法之重叠区间问题
  • BCLinux8.*构建部署nmap 7.95
  • 网络协议九 应用层 HTTPS
  • Spring Boot常用注解
  • MKS产品PECVD设备中应用PPT课件
  • 「Java 项目详解」API 文档搜索引擎(万字长文)
  • mapstruct学习笔记
  • STM32标准库学习笔记-1.基础知识
  • IOC--自定义IOC容器
  • windows安装android studio
  • 【ai】Easy-RAG 不行啊,RAGFlow官方demo行
  • 分布式日志
  • Vue是如何实现nextTick的?
  • Dockerfile搭建LNMP
  • 用Python实现9大回归算法详解——01. 线形回归算法
  • 《工厂模式在软件开发中的深度剖析与应用》
  • 苹果在iOS 18.1中向第三方开发者开放iPhone的NFC芯片
  • JavaScript AI 编程助手
  • Android之service两种启动方式的异同
  • 【自动驾驶】ROS远程节点的分布式通信
  • 一周人物|何子彦任职光州双年展,陈意心讲述五原路往事
  • 默茨在德国联邦议院第一轮投票中未能当选总理
  • 缅甸国防军继续延长临时停火期限至5月31日
  • 沪幼升小网上报名明起开始,是否参与民办摇号怎么定?
  • “注胶肉”或已泛滥?这几种肉,再爱吃也要管住嘴
  • 厦大历史系教授林汀水辞世,曾参编《中国历史地图集》