Docker镜像与容器:轻松理解与实战

目录

理解镜像和容器

docker命令

数据卷

匿名卷

自定义路径绑定挂载

自定义镜像

Dockerfile

网络

DockerCompose

一个c++可执行程序的镜像构建


理解镜像和容器

比如平时我们安装一个MySQL,需要下载安装包,解压,还有各种环境配置依赖等等,很麻烦

依赖就是MySQL需要哪些库,哪些Linux基础命令,也就是你的软件需要什么才能启动

预设的配置:MySQL的默认配置、端口映射、数据存储在哪等等

docker就是把这些一起打包给你,你直接解压就能够用了

这些整个的打包的东西叫镜像,也就类似模板,只是一个膜具

而你实例化出来的叫容器,就是一个实实在在的软件

最大的好处:

1.Docker会在运行容器的时侯创建一个隔离的环境,就是容器与宿主机(安装docker的机器)环境是隔离的,它有自己的独立的文件系统,网络空间和进程空间等,这就意味着,即使宿主机上有不同版本的软件,也不会影响容器内的应用

2.保证一致性,测试和生产使用同一个镜像,就能保证应用在不同的环境中的运行行为是一致的,解决了在我这能跑,在你那不行的问题

3.一台服务器是往往不同的应用之间有冲突,因为依赖可能不同,有了隔离环境就能隔离开

4.可以部署集群,也就是一台服务器上可以部署多个MySQL,避免了资源的浪费

docker命令

注意:对于一些命令的选项如果不了解,使用--help

如果有命令太长,可以在~/.bashrc中配置命令的别名,然后source ~/.bashrc就可以让这个配置文件生效

命令的详见官方文档:https://docs.docker.com/

1.docker ps:查看当前运行的docker容器

2.docker run:创建并且允许一个容器

-d:让容器在后台允许,如果没有这个选项就是前台,前台的话对于stdout等函数就会输出到你的终端,这样你就无法操作,只能ctrl+x这样就终止进程了,所以一般-d后台(守护进程)运行

--name:就是给容器起一个名字,比如mysql1,mysql2,用于区别不同的容器

-p:端口映射,宿主机端口:容器端口,比如mysql1的端口3306映射到宿主机3306,mysql2就不能映射到宿主机的3306,只能选择别的端口号

-e:设置环境变量,这个是由镜像的制作者也就是mysql的官方来弄的,怎么查,需要去文档,也就是dockerhub中查询

也就是run命令的最后一行 完整的应该是mysql:5.7(带上版本号,如果没有就是默认最新)

镜像仓库也就是你docker配置的镜像源,如果配置了阿里的那就去会阿里拉取,别人做的都放在镜像仓库中,pull就是拉到本地,run先会检查本地,如果本地没有就会去远端拉,注意:拉完本地也会有

注意:images就是镜像的意思,所以docker images就是看本地镜像

这里的stop停止容器是停掉这个进程,但容器还在,这不是删除

这里的build save load后面讲解

数据卷

在容器内部没有这些命令,说明在这个容器隔离的环境中只是装了nginx运行所需要的依赖和一些系统函数库,不是每个都装,不如ll,vim就没有,所以修改文件就很困难

所以提出了数据卷

进行一个双向的映射,即做一个绑定,宿主机当中修改会同步到容器,容器修改也会同步宿主机

所有的命令都是docker开头,然后操作的是数据卷,所以是docker volume

已经删除掉了Nginx,现在使用run命令直接在创建的时候实现挂载

使用docker volume ls查询的时候可以看到有个html的数据卷

可以看到对应关系,对应到/var/lib/docker/volumes/html/_data

/var/lib/docker/volumes是数据卷默认存放的目录,html是数据卷名,_data是数据卷实际存放数据的子目录

数据卷的好处:

1.数据持久化:容器的创建和删除十分方便,但是容器删除掉了之后,容器中的数据也没了,如果使用了数据卷就能给数据持久化,容器删除并不会影响到数据卷中的数据,当数据出现问题的时候,也可以使用数据卷备份和恢复

2.数据共享与迁移:多个容器可以挂载同一个数据卷完成数据共享,还可以进行跨主机迁移

匿名卷

命令docker inspect nginx,就可以查询到nginx容器的详细信息

这个是nginx之前挂载的数据卷

这个是mysql的,没有配置过,由容器运行的时候自动创建的,这种叫匿名卷,是自动生成的,往后mysql运行的数据就是存储在这里的

匿名卷产生的两种场景:

1.创建容器,当你用 -v--mount 挂载时,若只写了容器内需要挂载的路径,没指定宿主机路径或已存在的命名卷,Docker 会自动创建匿名卷并挂载到该容器路径。

2.部分官方镜像(如 MySQL、Redis、PostgreSQL)的 Dockerfile 会提前用 VOLUME 指令声明 "需要持久化的目录",目的是避免容器删除时数据丢失。(dockerfile是一个自动化构建镜像的文件)

注意:如果容器删除了,但这个匿名卷还是在的,所以数据还是在的,跟数据卷的特性一样

但匿名卷存在命名随机,不方便开发人员直接通过命名查看和维护,所以一般使用命名卷

自定义路径绑定挂载

你完全可以指定一个本地的目录来创建自定义路径的数据卷,不使用官方默认的路径

但注意docker volume之类的命令无法使用,因为没有在默认路径中是不由docker统一管理的

但是你可以通过宿主机的ls等命令来管理

自定义镜像

构建一个c++镜像的步骤:

1.准备一个Linux的运行环境

  1. 安装 C++ 编译器(如 g++、clang)和构建工具(如 make)

3.拷贝 C++ 源码或编译好的可执行文件

4.编写运行或编译运行的脚本(若需在容器内编译,可编写编译脚本;若直接运行可执行文件,可编写启动脚本)

对于docker不是把所有产生的文件压缩成一个,是每一层产生的文件压缩出来一个

所谓的镜像就是所有的压缩包合在一起而成的

镜像的结构

镜像是分层的,把每次操作都称为一层,所以我们之前在下载的时候,每一行显示的就是下载一个文件后进行解压,后续合并在一起就是一个完整的容器了

分层打包的好处

1.便于解耦,如果镜像都使用了相同的一层,这叫基础镜像,这样每次制作镜像的时候这一层就不需要考虑了

2.如果下载的时候b镜像的前两层和之前下载的a镜像的前两层一样,就不需要再下载了,这样就不会重复

总结:分层,结构清晰,但实际的操作复杂,为了简化,你只需要描述好入口和层和基础镜像就好

这样docker就会帮我们完成整个镜像的构建

Dockerfile

简单来说就是使用Dockerfile来描述镜像结构

总结一下之前的命令:也就是你构建好了镜像的结构/层次之后(dockerfile),使用命令build可以构建一个镜像,这个镜像就可以在不同的环境当中部署你的软件,docker save是将你的本地镜像打包成一个文件给别人,load就是把别人的镜像文件下载成本地镜像

网络

容器之间是相互隔离的,那容器之间是否可以相互访问呢

通过docker inspect 查看不同容器的详细信息

可以看到不同的容器当中ip地址不一样

一个是172.17.0.3

一个是172.17.0.4

说明是在同一个网段当中,因为他们有用一个网关(Gateway)

进入容器中,ping一下,发现是可以ping成功的

但是这样是有问题的,如果你当前容器stop了,别的容器启动就会分配ip地址,可能会占用你之前stop容器的ip地址,就会导致ip地址是可能会发生变换的,所以这种ip地址分配不是很好

所以产生了自定义网络

创建了一个test的自定义网络

通过ip addr查询可以看到多了一个网段172.18

容器与自定义网络相连

可以看到网络当中有两个,第一个就是创建容器的时候默认的,第二个就是test自定义网络

当然你可以创建的时候使用--network test 直接与自定义网络相连,这样就不会生产默认的了

然后进入容器ping一下test中的ip地址也是成功的或者直接ping test中其他的容器名

(注意只有处于同一组网络中才能ping成功的,因为网络具有隔离性)

自定义网络的好处:

1.容器间通信便捷与灵活:可以将不同组的容器分在不同的网络组中,实现通信隔离;一个容器还可以加入多个组,实现更复杂的通信场景;可以直接使用ping 容器名来通信,不必像之前一样ping ip地址,而且ip地址也会变换

DockerCompose

就是帮你一条龙服务

当应用需要多个容器协同工作时(例如:一个 Web 应用 + 一个数据库 + 一个缓存服务),手动管理每个容器的启动顺序、网络连接、数据卷挂载 等会非常繁琐。docker-compose 解决了这个问题:

  • 用一个配置文件定义所有容器的参数(镜像、端口、网络、依赖关系等)
  • 一键启动 / 停止 / 重启所有关联容器
  • 自动处理容器间的网络连接(无需手动手动创建网络)

dockercompose配置文件中的信息跟run命令中的是差不多的

一个c++可执行程序的镜像构建

写一个可执行程序,也就是相当于你的软件

注意这个Dockerfile文件,docker会从上往下扫,逐行执行

WORKDIR:就是再容器内部创建目录,你后续的命令如COPY main.cpp . 就是把这个文件拷贝到容器中的WORKDIR的创建的目录

CMD就是别人启动容器的时候执行的,所以这里就是直接进入容器的交互式终端,由于前面WORKDIR设置了目录,所以直接就进行这个目录

注意:

1.EXPOSE就是设置端口号,如果你的程序当中绑定监听了某个端口号,你就需要EXPOSE提示使用者你可能绑定了什么端口号,这样它在未来使用容器的时候-p 宿主机端口号:镜像人绑定的端口号,使用者需要知道你绑定了哪个端口号,要进行映射

2.CMD与ENTRYPOINT的区别

CMD命令,如果使用容器的人在run命令中使用了额外的命令在最后就会覆盖掉CMD中的参数,前面的-p -v等不影响

ENTRPOINT不会覆盖,会追加在后面

现在我们简单写了一个Dockerfile,使用build构建一下镜像就可以,之后的命令就是运行

相关推荐
一叶知秋yyds2 分钟前
Ubuntu 虚拟机安装 OpenClaw 完整流程
linux·运维·ubuntu·openclaw
斯普信云原生组42 分钟前
Prometheus 环境监控虚机 Redis 方案(生产实操版)
运维·docker·容器
喵了几个咪1 小时前
如何在 Superset Docker 容器中安装 MySQL 驱动
mysql·docker·容器·superset
工具罗某人1 小时前
docker compose部署kafka集群搭建
docker·容器·kafka
safestar20122 小时前
ES批量写入性能调优:BulkProcessor 参数详解与实战案例
java·大数据·运维·jenkins
来一颗砂糖橘2 小时前
负载均衡的多维深度解析
运维·负载均衡
楠奕2 小时前
CentOS7安装GoldenDB单机搭建及常见报错解决方案
linux·运维·服务器
GCTTTTTT3 小时前
远程服务器走本地代理
运维·服务器
剑锋所指,所向披靡!3 小时前
Linux常用指令(2)
linux·运维·服务器
飞Link3 小时前
逆向兼容的桥梁:3to2 自动化降级工具实现全解析
运维·开发语言·python·自动化