Docker 学习笔记

本文介绍了Docker作为一种容器化技术,如何简化应用部署,提供快速交付、便捷升级和高效资源利用。文章详细讲解了Docker的工作原理、镜像概念、镜像分层、容器生命周期管理、数据卷、网络设置,以及DockerCompose在编排多容器项目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Docker概述

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

为什么要有Docker

传统:发布一个项目时无法将环境一起打包,部署时配置环境十分麻烦,费时费力。

现代:开发打包部署上线一套完成,打包项目时带上环境,称为镜像。使用时下载发布的镜像直接运行即可。

在容器化技术出现以前,一机多用通过虚拟机技术实现

虚拟机:虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统中安装和运行软件,代码还没运行就已经占了庞大的系统资源,非常笨重。

Docker容器技术:也是一种虚拟化技术,但Docker镜像只包括最核心的环境,十分小巧,运行时直接运行镜像就可以了。每个容器间使用沙箱机制相互隔离,互不影响。

使用Docker的好处

更快速的交付和部署应用

传统:一堆帮助文档、安装复杂的环境和程序

Docker:打包镜像、发布测试、一键运行

更便捷的升级和扩缩容

如果一个服务器性能达到瓶颈,可以直接在另一台服务器上运行镜像进行扩展

更高效的计算资源利用

保证了线上线下环境的一致性

实现了沙箱机制,提高了安全性

Docker为什么比VM快

1.docker 有着比虚拟机更少的抽象层
由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接试用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显的优势。。

2.docker利用的是宿主机的内核,而不需要加载操作系统的OS内核
当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载OS,返回新建的过程时分钟级别的,而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。

在这里插入图片描述

Docker基本组成

镜像(image):

相当于是一个模板,可以通过这个模板来创建一个或多个容器,最终服务或项目运行就是在容器中的

容器(container):

Docker通过容器独立运行一个或一组应用,可以执行启动、停止、删除等基本命令

仓库(repository):

仓库就是存放镜像的地方,分公有仓库和私有仓库

Docker是怎么工作的?

Docker是一个C/S结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问

DockerServer接收到DockerClient的命令,就会执行这个命令

Docker常用命令

帮助命令

docker version	#显示docker的版本信息
docker info		#显示docker系统详细信息
docker 命令 --help #帮助命令

容器生命周期管理

docker run #创建一个新的容器并运行一个命令
docker start #启动一个或多个已经被停止的容器
docker stop #停止一个运行中的容器
docker restart #重启容器
docker kill #杀死一个运行中的容器。
docker rm #删除一个或多个容器。如果要删除一个运行中的容器,可以添加 -f 参数。
docker prune #删除所有处于终止状态的容器
docker pause #暂停容器中所有的进程。
docker unpause #恢复容器中所有的进程。
docker create #创建一个新的容器但不启动它

容器操作

docker ps	#列出容器
docker inspect	#获取容器、镜像的元数据
docker top	#查看容器中运行的进程信息
docker exec #在运行的容器中执行命令,进入容器后开启一个新的终端,可以在里面操作,退出应用时不会导致容器停止
docker attach	#连接到正在运行中的容器,进入容器正在执行的任务,不会启动新的进程。退出应用时会导致容器停止
docker events	#从服务器获取实时事件
docker logs	#获取容器的日志
docker wait	#阻塞运行直到容器停止,然后打印出它的退出代码。
docker export	#将文件系统作为一个tar归档文件导出到STDOUT。
docker port	#列出指定的容器的端口映射,或者查找将PRIVATE_PORT NAT到面向公众的端口。
docker commit #从容器创建一个新的镜像。
docker cp #用于容器与主机之间的数据拷贝。
docker diff #检查容器里文件结构的更改。

镜像仓库

docker login	#登陆到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker logout :#登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker pull	#从镜像仓库中拉取或者更新指定镜像
docker push	#将本地的镜像上传到镜像仓库,要先登陆到镜像仓库
docker search	#从Docker Hub查找镜像

本地镜像管理

docker images #列出本地镜像
docker rmi	#删除本地一个或多个镜像
docker tag	#标记本地镜像,将其归入某一仓库
docker build	#使用 Dockerfile 创建镜像
docker history	# 查看指定镜像的创建历史
docker save	#将指定镜像保存成 tar 归档文件
docker load	#导入使用 docker save 命令导出的镜像
docker import	#从归档文件中创建镜像

Docker镜像

什么是镜像

  • 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。只有通过镜像文件才能生成容器实例。
  • 将所有的应用和环境,直接打包为docker镜像,就可以直接运行。
  • 如何得到镜像:
    • 从远处仓库下载
    • 拷贝
    • 自己制作一个镜像 DockerFile

Docker镜像加载原理

  • Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是 UnionFS

    • **UnionFS(联合文件系统):**Union文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是 Docker镜像的基础,**可以通过分层来继承基础镜像,提高文件的复用。**说白了就是把一个镜像分成很多层,多个镜像可以共用相同的一层,避免了文件的重复加载。
    • 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
  • bootfs(boot file system)主要包含bootloader加载器和kernel内核。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。

  • rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。所以虚拟机启动是分钟级,而docker能做到秒级。docker 的镜像文件相当于=只拥有自己的bootfs+简单的rootfs+镜像本身的依赖+镜像本身

  • Docker镜像都是只读的,当容器启动时, 一个新的可写层被加载到镜像的顶部!这一层就是我们通常说的容器层, 容器之下的都叫做镜像层。在这里插入图片描述

commit镜像

docker commit 提交容器成为一个新的镜像 和Git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id	目标镜像名:[tag]

使用 docker commit 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。

除了真正想要修改的文件外,由于命令的执行,还有很多文件被改动或添加。如果是安装软件包、编译构建,那会有大量的无关内容被添加进来,将会导致镜像极为臃肿。

此外,使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。

容器数据卷

目的:为了实现数据持久化,并且使容器之间能够共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。

使用数据卷

  • 直接使用命令来挂载 -v,挂载成功后其实是双向绑定,无论在哪一端修改文件内容都可以同步到另一端

    docker run -it -v 主机目录:容器内目录
    

    使用docker inspect命令查看容器的详细信息,可以看到下面这张图,表示挂载成功

    在这里插入图片描述

    好处:以后修改数据直接在本地和容器内修改都可以,另一端会自动同步,并且删除容器之后,本地的数据依旧存在,做到了容器数据的持久化

匿名挂载和具名挂载

匿名挂载

-v 容器内路径 #只指定容器内路径,本地路径由docker自动配置

[root@localhost ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx	
[root@localhost ~]# docker volume ls 	#查看所有数据卷
local     45de0c847c7ff79692f4bd0aabd7936e11a9dc91bc85fab00eae323cc65cd1d0
  • 补充:docker volume 命令 操作数据卷

      create      Create a volume
      inspect     Display detailed information on one or more volumes
      ls          List volumes
      prune       Remove all unused local volumes
      rm          Remove one or more volumes
    

具名挂载

-v 卷名:容器内路径

[root@localhost ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
673298470e5e9d5d8c2e51e638372fd166f35873e7b960b3c00e780f972288dd
[root@localhost ~]# docker volume ls
local     juming-nginx

使用docker volume inspect 命令查看数据卷详细信息:

在这里插入图片描述

在没有指定目录的情况下,所有docker容器的卷都是在 /var/lib/docker/volumes/xxxx/_data

查看一下这个目录:

在这里插入图片描述

通过具名挂载可以方便的找到我们的一个卷,大多数情况下使用具名挂载

#小结
-v 容器内路径					#匿名挂载
-v 卷名:容器内路径				  #具名挂载
-v /宿主机路径:/容器内路径		#指定路径挂载

#拓展:通过-v 容器内路径:ro(只读) rw(读写) 改变读写权限
#一旦设置了这个容器的权限,容器对挂载出来的内容就有限定了
#如果设置了ro,那容器就只有只读权限了,只能通过宿主机才能进行写操作
[root@localhost ~]# docker run -d -P --name nginx01 -v /etc/nginx:ro nginx	

此外,在使用DockerFile构建镜像时也可以挂载,在下一节具体说明

DockerFile

DockerFile就是用来构建Docker镜像的文件 其实就是一段命令脚本

看一看官方的dockerfile:

在这里插入图片描述

很多官方的镜像都只有基础包,我们通常会搭建自己的镜像

构建步骤:

  1. 编写一个DockerFile文件
  2. docker build 将dockerfile构建为一个镜像
  3. docker run运行镜像
  4. docker push发布镜像(DockerHub、阿里云镜像仓库)

在这里插入图片描述

DockerFile指令

FROM		#指定基础镜像,一切从这里开始构建,必需指令,而且必须是第一条指令
MAINTAINER	#镜像作者,姓名+邮箱
RUN			#执行命令行命令
COPY		#复制文件
ADD			#复制文件,会自动解压,除非需要解压,否则更推荐用COPY
WORKDIR		#镜像的工作目录
VOLUME		#挂载的目录
EXPOSE		#保留端口配置
CMD			#指定默认的容器主进程的启动命令,只有最后一个会生效,可被替代
ENTRYPOINT	#指定容器启动的时候要运行的命令,可以追加命令

在这里插入图片描述

构建一个自己的centos

#1.编写dockerfile文件
vim dockerfile-centos	#文件名可以随意,但最好是dockerfile

FROM centos:7
MAINTAINER linhongwei<1332009068@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim	#官方的centos是没有vim功能的,这里我们把它加进去
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

#2.通过这个文件构建dockerfile对象
#docker build -f dockerfile文件路径 -t 镜像名:[tag版本号] .
docker build -f dockerfile-centos -t mycentos .	#一定要注意这里还有个.

build好之后就可以使用docker images查看镜像

在这里插入图片描述

使用docker run命令创建一个容器

在这里插入图片描述

然后进入这个容器,使用vim命令创建一个新文件,可以看到我们自己构建的centos镜像拥有了vim功能

在这里插入图片描述

可以使用docker history命令来查看镜像的构建过程

在这里插入图片描述

Docker网络

理解Docker网络

在这里插入图片描述

我们进入一个Tomcat容器,看一看它的host信息

在这里插入图片描述

172.17.0.2就是docker分配给这个Tomcat容器的地址,那么我们能在容器外ping通这个地址吗?

可以看到,是可以ping通的。说明Linux可以ping通docker容器内部

在这里插入图片描述

原理:

  • 我们每启动一个docker容器,docker就会给容器分配一个ip,我们只要安装了docker,就会有一个docker0网卡,使用桥接模式,使用的技术是veth-pair技术
  • veth-pair就是一对虚拟设备接口,成对出现,一端连着协议,一端彼此相连,充当一个桥梁。

那么,再新建一个容器tomcat02,我们能在tomcat02内ping通tomcat01吗?

这里有可能会出现没有ping命令的情况,原因是我们下载的tomcat版本是精简版,阉割掉了ping命令,我们可以在容器内使用下面的几条命令安装进去。

先apt update
然后apt install -y net-tools
apt install -y iproute2
apt install -y iputils-ping

可以看到,也能ping通。说明容器之间也可以互相ping通

在这里插入图片描述

容器之间是通过docker0网卡连接的,docker0就相当于是容器1和容器2之间的一个交换机。docker内部的所有网络接口都是虚拟的,转发效率高。

在这里插入图片描述

容器互联 --link

在启动容器时使用–link

[root@localhost ~]# docker run -d -P tomcat03 --link tomcat02 tomcat

用tomcat03ping一下tomcat02试试

在这里插入图片描述

查看tomcat03的host配置,发现–link其实就是在tomcat03 的host中增加一条tomcat02的配置

在这里插入图片描述

–link缺点:不支持自定义网络,所以不建议使用

自定义网络

查看所有的docker网络

在这里插入图片描述

网络模式

bridge:桥接 docker默认

none:不配置网络

host:和宿主机共享网络

container:容器网络连通,局限大,很少用

# 我们直接启动的命令其实默认有一个 --net bridge 这个其实就是docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat

#docker0 特点:默认,域名不能访问,--link可以打通网络

自定义网络

[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
d5c23a994ae84cb543d87aea0a789013f59690949c0f25e4dee5ad6c28a13c04

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
becd1cb6fe8a   bridge    bridge    local
67bcc99d7c78   host      host      local
d5c23a994ae8   mynet     bridge    local
38d15644633c   none      null      local

查看我们自己创建的网络mynet的详细信息在这里插入图片描述

在mynet中创建两个容器在这里插入图片描述

再查看网络的详细信息,可以看到我们创建的两个容器都在网络里面了

在这里插入图片描述

可以看到,自定义的网络内的容器可以ping分配的IP,也可以直接ping容器名在这里插入图片描述

网络连通

测试连通tomcat02 - mynet(不同虚拟网卡(网段)之间不能直接连通,但是容器可以和虚拟网卡连通)

 [root@localhost ~]# docker network connect mynet tomcat02
  [root@localhost ~]# docker network inspect mynet

在这里插入图片描述

连通方式非常简单粗暴,就是直接在mynet网络中给tomcat02分了一个IP地址

可以看到:tomcat02可以ping通mynet里的其他容器了,但是tomcat03不能ping通在这里插入图片描述

Docker Compose

Compose是Docker的官方开源项目,可以进行批量容器编排,轻松高效地管理Docker容器集群。你需要定义一个yaml配置文件docker-compose.yml,写好多个容器之间的调用关系,然后,只需要一个命令就可以同事启动/关闭这些容器。Compose解决了容器与容器之间如何管理编排的问题。

术语

  • 服务 (service):当我们运行某个镜像时,其实就产生了一个镜像实例,这个实例我们把它叫做容器,接下来我们对它做个升级,比如一些配置负载均衡,配置域名解析映射等,最终它以web服务的形式运行,那么这个升级版的容器就是Docker服务。

  • 项目 (project):Compose允许用户通过一个单独的docker-compose.yml模板文件来定义一组关联的应用容器为一个项目。

    可见,一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

#yaml文件示例
version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

容器,接下来我们对它做个升级,比如一些配置负载均衡,配置域名解析映射等,最终它以web服务的形式运行,那么这个升级版的容器就是Docker服务。

  • 项目 (project):Compose允许用户通过一个单独的docker-compose.yml模板文件来定义一组关联的应用容器为一个项目。

    可见,一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

#yaml文件示例
version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值