深入理解Docker,从入门到精通-Part1(基础使用)

news/2024/12/27 22:40:37/

一、Docker基本概念

Docker架构


基本组件的介绍

Docker Client 是用户界面,它支持用户与Docker Daemon之间通信
Docker Daemon Docker最核心的后台进程,运行于主机上,处理服务请求
Docker registry是中央registry,支持拥有公有与私有访问权限的Docker容器镜像的备份
Docker Containers负责应用程序的运行,包括操作系统、用户添加的文件以及元数据
Docker Images是一个只读模板,用来运行Docker容器
DockerFile是文件指令集,用来说明如何自动创建Docker镜像

三个基本概念

镜像

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等),镜像不包含任何动态数据,其内容在构建之后也不会被改变。

简单理解,镜像就是一个文件,特殊之处在于能被Docker加载运行

但实际上并不是由单个文件组成那么简单,背后是一个文件系统,采用分层存储。

分层存储指的是镜像是由一组文件系统组成,或者说,由多层文件系统联合组成。

关键技术就是Union FS,联合文件系统是(Union FS)是linux的存储技术,也是Docker镜像的存储方式, 它是分层的文件系统,将不同目录拉到同一个虚拟目录下,下图展示了Docker用Union FS 搭建的分层镜像:(比如最下层是操作系统的引导,上一层是Linux操作系统,再上一层是Tomcat,jdk,再上一层是应用代码)

镜像构建时,会一层层构建,前一层是后一层的基础,每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。(比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除,在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像,因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉)

容器

镜像和容器的关系,就像是面向对象程序设计中的 类 和 实例 一样

镜像是静态的定义,容器是镜像运行时的实体,容器可以被创建、启动、停止、删除、暂停等。

        容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间,因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。
        容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样,这种特性使得容器封装的应用比直接在宿主运行更加安全。
        前面讲过镜像使用的是分层存储,容器也是如此,每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。
        容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡,因此,任何保存于容器存储层的信息都会随容器删除而丢失。

仓库

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜
像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个仓库( Repository );每个仓库可以包含多个标签
Tag );每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本,我们
可以通过 < 仓库名>:<标签 > 的格式来指定具体是这个软件哪个版本的镜像,如果不给出标签,将以 latest 作为默认标签。
仓库名经常以 三段式路径 形式出现,比如 demo.com/nginx - proxy:tag ,前者往往意味着 Docker
Registry 多用户环境下的用户名,后者则往往是对应的软件名,但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务

二、Docker安装部署MySQL

1、下载镜像,这里以mysql5.7.41版本为例

docker pull mysql:5.7.41

2、 mysql配置

创建MySQL挂载目录,等会会解释什么是挂载路径

# 创建MySQL配置的文件夹
mkdir -p /tmp/etc/mysql
# 编辑my.cnf配置文件
vi /tmp/etc/mysql/my.cnf

配置MySQL忽略大小写,在我们创建的MySQL配置文件挂载点的目录的my.cnf文件加入如下内容

[mysqld]
lower_case_table_names=1

创建MySQL数据目录

因为默认MySQL启动后他的文件是在容器中的,如果我们删除容器,数据也将会消失,我们需要将数据挂载出来。

#创建mysql存储的目录
mkdir -p /tmp/data/mysql

启动MySQL

docker run -d -p 3306:3306 -v /tmp/etc/mysql:/etc/mysql/mysql.conf.d/ -v /tmp/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql mysql:5.7.41

docker ps查询,出现如下结果表明mysql启动成功

参数解释

  • -d:是指容器后台运行,如果不加-d,当用户断开客户端时容器会结束运行
  • -p:将容器的3306端口映射到主机的3306端口,用来暴漏端口的
  • -v:这个命令是用来挂载目录的,将本地目录挂载到容器中,这样容器操作的就是本地目录
  • -e:这个命令是配置环境参数的,这里MYSQL_ROOT_PASSWORD=root指的是用root用户运行mysql,可以登录Docker容器通过ENV命令查看
  • --name:这个命令是配置Mysql的容器名称的,如果不配置,默认是随机生成的名字

查看容器挂载的配置文件

可以通过docker exec -ti mysql /bin/bash命令登录容器,检查挂载的配置文件情况

我们可以看到我们修改的配置文件已经被挂载到了docker内部,这里面用到了exec命令,主要是在docker容器中运行命令

docker exec就是进入容器的命令,其中

-t 表示命令行交互模式      -i 表示展示容器输入信息STDIN

至此,MySQL安装部署成功

三、Docker安装部署Nacos

1、下载镜像,这里以nacos2.0.1版本为例

docker pull nacos/nacos-server:2.0.1

2、运行镜像

docker run -d -p 8848:8848 --name nacos --env MODE=standalone nacos/nacos-server:2.0.1

参数解释:

-d:后台进程运行

--name:容器名称

--env MODE=standlone:设置环境变量,这里表示单机模式启动

登录控制台,成功显示

至此,Nacos单机版安装部署成功

四、SpringBoot项目部署

将项目通过Maven进行打包,再去Target目录复制Jar包文件上传至服务器

 编写DockerFile文件

vi Dockerfile

具体内容如下:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD learn-docker-storage-1.0-SNAPSHOT.jar app.jar
EXPOSE 8003
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]

命令解释:

  • FORM:定制的镜像都是基于 FROM 的镜像,这里的 openjdk 就是定制需要的基础镜像,后续操作都是基于openjdk
  • VOLUME:挂载一个数据卷,这里因为没有名称,所以是一个默认的数据卷(后面详细解释)
  • ADD:添加一层镜像到当前镜像,这里就是添加SpringBootTest镜像到当前层,并改名app.jar
  • EXPOSE:暴漏端口,因为我们的自己的端口是8003,所以我们暴漏8003
  • ENTRYPOINT:设定容器启动时第一个运行的命令及其参数,这里就是容器以启动就执行 java -jar /app.jar

写好DockerFile后就需要用docker build命令来构建我们的镜像了,这样就可以将我们的SpringBoot项目打包成一个镜像了

构建一个镜像需要使用以下命令

docker bulid -t 仓库名/镜像名:tag .
  • -t  镜像的名字及标签,一般命名规则是 仓库名/镜像名:tag,

    • 仓库名:一般是私服或者dockerhub等地址,如果忽略默认就是dockerhub的地址docker.io.library/
    • 镜像名称:就是我们的自己的服务名称,可以随意命名
    • tag:就是我们的版本号
  • .  这个 . 表示当前目录,这实际上是在指定上下文的目录是当前目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

docker build -t learn-docker-storage:0.0.1 .

 

构建完成如果出现Successfully说明已经构建成功了

可以查看我们构建的镜像

启动镜像:

# 运行容器
docker run -d -p 8003:8003 learn-docker-storage:0.0.1

 查看启动日志

docker logs -f container_id

至此,我们的打包镜像部署服务就已经大功告成了

五、日志挂载优化

存储卷优化

什么是存储卷

“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某个目录“绑定
(关联)”;

Docker 中,要想实现数据的持久化(所谓 Docker 的数据持久化即 数据不随着 Container 的结束
而结束 ),需要将数据从宿主机挂载到容器中。这些数据比如Mysql的数据、redis的数据、日志数据等等
Docker 管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;( 最常用的方

存储卷的使用

 查看存储卷

docker volume ls

 

我们发现都是匿名的存储卷,如何来确定都是那个呢,可以通过 docker inspect 容器 ID 来查看
存储信息
docker inspect 2041965c3e87|grep Mounts -A20

# 进入文件挂载目录 
cd /var/lib/docker/volumes/d35de1b7e4631908b05635db4c1f114ab3aafbdf25a9843c068696e6 6a779c75/_data 
# 输出日志 
tail -f learn-docker-storage.log

 当删除了容器,发现存储卷所挂载的目录数据依然还存在

bind挂载共享存储

什么是bind

Bind mounts模式和Volumes非常相似,不同点在于Bind mounts模式是将宿主机上的任意文件或文件夹挂载到容器,而Volumes本质上是将Docker服务管理的一块区域(默认是/var/lib/docker/volumes下的文件夹)挂载到容器。

共享存储

经过上面的测试,我们发现每一个容器都是单独用一个存储卷,用于临时文件没有问题的,但是如果要让容器都用同一个存储路径怎么办呢,这个时候就用到了 bind挂载了,可以使用-v进行挂载挂载刚才的存储卷。

# 级联创建文件夹
mkdir -p /tmp/data/logs
# 运行容器,指定挂载路径 
docker run -d -v /tmp/data/logs:/logs \
-p 8003:8003 --name learn-docker-storage \
learn-docker-storage:0.0.2

 用-v来指定需要挂载的目录,这也是我们用的最多的一种方式

使用docker inspect命令来检查容器详情

docker inspect learn-docker-storage|grep Mounts -A20

volume和bind的区别

对于多个容器需要共享访问同一数据目录,或者需要持久化容器内数据(如数据库)时,我们都是采用挂载目录形式(bind mounts),将宿主机的某一目录挂载到容器内的指定目录,这种方式能解决问题,但这种方式也一直有一些缺点

  • 容器在不同的服务器部署需要根据实际磁盘挂载目录修改路径
  • 不同操作系统的文件和目录权限会搞得你昏头转向,火冒三丈 ?

 bind mount和volume其实都是利用宿主机的文件系统,不同之处在于volume是docker自身管理的目录中的子目录,所以不存在权限引发的挂载的问题,并且目录路径是docker自身管理的,所以也不需要在不同的服务器上指定不同的路径,你不需要关心路径。

六、网络优化

我们先用一张图来说明为什么要进行网络优化

所以Docker的容器是否可以直接通过Docker的网卡进行直接通信呢?

答案是当然可以,这就叫做网络优化。

Docker网络原理

        Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关,因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

       Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器,如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

docker网络模式">Docker网络模式

Docker网络模式配置说明
host模式–net=host容器和宿主机共享Network namespace。
container模式–net=container:NAME_or_ID容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
none模式–net=none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
overlay模式-- driver overlayDocker跨主机通信模式,使用分布式计算机架构后需要使用overlay网络模式
bridge模式–net=bridge(默认为该模式)

 Docker 的 bridge 模式是 Docker 容器网络的默认模式,它提供了一种简单而强大的方式来为容器分配独立的 IP 地址,并使它们能够在同一主机上相互通信。下面是对 bridge 模式的简要介绍:

桥接网络模式实战

查看网络列表

可以通过docker network ls命令查看网络列表

# 查看网络列表
docker network ls

创建一个桥接网络

默认容器启动会自动默认接入bridge的桥接网络,为了区分我们的服务也防止各种网络问题,我们创建一个专用网络,可以通过docker network create 网络名称来创建一个默认的桥接网络

# 创建一个桥接网络
docker network create learn-docker-network
# 查看网络列表
docker network ls

停止并删除原有容器

停止和删除我们的微服务以及mysql服务

# 删除当前运行中的容器
docker rm -f learn-docker-storage nacos mysql

创建MySQL

因为我们的微服务依赖MySQL先启动MySQL并接入网络,因为MySQL不需要通过宿主机访问,所有也不需要映射端口了,--network 是配置接入哪一个网络

docker run -d \
-v /tmp/etc/mysql:/etc/mysql/mysql.conf.d/ \
-v /tmp/data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
--name mysql --network=learn-docker-network \
mysql:5.7.38

这里需要注意:为什么重新建了个新的MySQL容器,能拿到以前的数据?因为我们做了存储卷映射,所以数据可以持久化

创建Nacos

我们的nacos是需要暴露端口的,因为我们需要外部能够看到nacos页面,但是我们也需要我们的nacos连接到当前网络

docker run -d  \
--network=learn-docker-network \
-p 8848:8848 \
--name nacos --env MODE=standalone \
nacos/nacos-server

查看网络详情

可以通过docker network inspect 网络名称可以查看当前的网络的详细信息

docker network inspect learn-docker-network

修改微服务配置

因为需要使用自定义网络访问mysql容器以及nacos容器,需要修改微服务数据库连接地址,

docker 网络访问 可以通过IP或者通过服务名称都是可以的,这里我们通过服务名称访问,因为我们使用了maven打包的方式,我们只需要将pom文件修改就可以

<properties><mysql.addr>mysql:3306</mysql.addr><nacos.addr>nacos:8848</nacos.addr>
</properties>

重新打包服务

将打包的文件上传服务器后按照上面步骤同上面打包,打包版本为 0.0.3

docker build -t learn-docker-storage:0.0.3 .

创建微服务

下面就按部就班的创建微服务就可以,只是注意需要加入网络,这里这个端口需要映射外网访问

docker run -d \
-v /tmp/data/logs:/logs \
-p 8003:8003 \
--name learn-docker-storage \
--network=learn-docker-network \
learn-docker-storage:0.0.3

测试微服务

到现在微服务已经启动,我们尝试访问以下

 curl http://192.168.64.153:8003/storage/employe/findByID/10001 | python -m json.tool

访问测试数据没有问题,到现在我们服务已经搭建完成,并且使用网络进行了优化


http://www.ppmy.cn/news/1543300.html

相关文章

《原子核物理评论》

《原子核物理评论》报道原子核物理基础研究、应用研究以及与此有关的交叉学科研究领域的最新重要研究成果和发展趋势, 促进本学科及相关交叉学科的发展&#xff0c;增进国内外学术交流。主要刊登反映本学科及相关各交叉学科领域最新进展的评述性文章, 同时及时发表最新重要研究…

Elasticsearch 安装教程:驾驭数据海洋的星际导航仪

目录 一、准备工作1. ES的下载 二、安装步骤三、注意事项四、启动报错1. org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root2. max virtual memory areas vm.max_map_count [65530] is too low, increase to at l…

基于数字图像处理人民币面额自动识别

自动缴费机、存取款一体机和自动售货机出现在了我们的生活中。这些先进的设备中最重要的一门技术就是&#xff1a;纸币识别技术。当我们将钞票投入缴费机或者存款机时&#xff0c;机器必定会首先识别用户投入的是面额为多少的纸币&#xff0c;之后再进行真伪辨别、数据写入等功…

【Linux】ProxySQL读写分离

proxysql-2.7.1-1-centos7.x86_64.rpm 读写分离 读写分离的概念 读写分离是⼀种数据库优化技术&#xff0c;主要⽬的是通过将数据库的读操作和写操作分散到不同的数据库 实例上&#xff0c;来提⾼数据库的整体性能和可扩展性。其基本原理是让主数据库处理事务性增、改、删操…

Github 2024-10-30C开源项目日报 Top10

根据Github Trendings的统计,今日(2024-10-30统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目10C++项目1PHP项目1PHP:流行的Web开发脚本语言 创建周期:4710 天开发语言:C, PHP协议类型:OtherStar数量:37340 个Fork数量:7657 次…

微信小程序-全局数据共享/页面间通信

一.全局数据共享 声明全局的变量&#xff0c;在app.js文件里 App({//全局共享的数据globalData:{token:},//设置全局数据setToken(token){this.globalData.tokentoken}})使用 getApp() 获取全局App实例 //返回全局唯一的APP实例 const appInstancegetApp()Page({login(){con…

3D点云与2D图像的相互转换:2D图像对应像素的坐标 转为3D空间的对应坐标

2d ----> 3d 对应像素到空间坐标的转换 参考&#xff1a;深度相机&#xff0c;通过2d检测得到目标坐标系的3d检测框_深度图到相机坐标-CSDN博客

【webpack学习】

webpack由于历史包袱导致复杂&#xff0c;只要把握关键流程即可 webpack的主要流程loader plugin难点&#xff1a;HMR / 懒加载 原理webpack 的优化手段 构建工具对比 webpack &#xff1a;可以打包任何资源&#xff0c;配置略复杂&#xff0c;适合项目开发rollup&#xff1…