Docker学习笔记

尚硅谷2022版Docker实战教程(docker教程天花板)
跟着周阳老师学的

Docker简介

Docker是基于Go语言实现的云开源项目。
Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次镜像,处处运行”。

Linux容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用打成镜像,通过镜像成为运行在Docker容器上面的实例,而 Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

解决了运行环境和配置问题的软件容器,
方便做持续集成并有助于整体发布的容器虚拟化技术。

Docker常用命令

镜像命令

1.docker images

列出本地主机上的镜像

各个选项说明:

  • REPOSITORY:表示镜像的仓库源
  • TAG:镜像的标签版本号
  • IMAGE ID:镜像ID
  • CREATED:镜像创建时间
  • SIZE:镜像大小

同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

OPTIONS说明:

  • -a :列出本地所有的镜像(含历史映像层)
  • -q :只显示镜像ID。

在这里插入图片描述

2. docker search [OPTIONS] 镜像名字

OPTIONS说明:

  • –limit : 只列出N个镜像,默认25个
  • docker search --limit 5 redis
    在这里插入图片描述在这里插入图片描述

3. docker pull 镜像名字[:TAG]

没有TAG就是最新版,等价于 docker pull 镜像名字:latest
示例:docker pull redis
在这里插入图片描述

4. docker system df 查看镜像/容器/数据卷所占的空间

在这里插入图片描述

5. docker rmi 某个XXX镜像名字ID (删除镜像)

  • 删除单个:docker rmi -f 镜像ID
  • 删除多个:docker rmi -f 镜像名1:TAG 镜像名2:TAG
  • 删除全部:docker rmi -f $(docker images -qa)
    在这里插入图片描述

容器命令

1.docker run [OPTIONS] IMAGE [COMMAND] [ARG…] (新建+启动容器)

OPTIONS说明(常用):有些是一个减号,有些是两个减号

  • –name=容器新名字 : 为容器指定一个名称;

  • -d:后台运行容器并返回容器ID,也即启动守护式容器(后台运行);

  • -i:以交互模式运行容器,通常与 -t 同时使用;

  • -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
    也即启动交互式容器(前台有伪终端,等待交互);

  • -P:随机端口映射,大写P

  • -p:指定端口映射,小写p

1.进入新建名为myub1的ubuntu容器
在这里插入图片描述
2.查看正在运行的容器,发现ubuntu正在运行
在这里插入图片描述

2.docker ps [OPTIONS]: 列出容器

没加OPTIONS只显示正在运行的容器

OPTIONS说明:

  • -a :显示所有的容器,包括未运行的。

  • -l :显示最近创建的容器。

  • -n :列出最近创建的n个容器。

3.退出容器

  • exit:run进去容器,exit退出,容器停止
  • run进去容器,ctrl+p+q退出,容器不停止

4.启动已停止运行的容器:docker start 容器ID或者容器名

5.重启容器:docker restart 容器ID或者容器名

6.停止容器:docker stop 容器ID或者容器名

7.强制停止容器:docker kill 容器ID或容器名

8.删除已停止的容器:docker rm 容器ID

9.启动守护式容器(后台服务器)

在大部分的场景下,我们希望 docker 的服务是在后台运行的,
我们可以过 -d 指定容器的后台运行模式。

  • 前台交互式启动: docker run -it redis
  • 后台守护式启动:docker run -d redis
    在这里插入图片描述

10.查看容器日志:docker logs 容器ID

在这里插入图片描述

11.查看容器内运行的进程:docker top 容器ID

在这里插入图片描述

12.进入正在运行的容器并以命令行交互

docker exec -it 容器ID/名字 bash
docker exec -it 容器ID/名字 sh
有的用sh才能进去,奇怪
在这里插入图片描述
退出容器输入exit即可
推荐大家使用 docker exec 命令,因为退出容器终端,不会导致容器的停止。

13.导入导出容器

docker export 容器id > 导出名.tar 会导出在当前目录下
cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号,下面例子,发现已成功导入并运行了一个实例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Docker镜像

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。分层时有文件更新直接替换,基础镜像一样时直接拿过来复用。

如redis下载不同版本时,第一层相同,直接复用,其他几层分层下载。

afb6ec6fdc1c: Already exists 
608641ee4c3f: Pull complete 
668ab9e1f4bc: Pull complete 
78a12698914e: Pull complete 
d056855f4300: Pull complete 
618fdf7d0dec: Pull complete 

参考:彻底搞懂Docker镜像分层

Docker镜像commit操作案例

docker commit提交容器副本使之成为一个新的镜像

docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

原始的默认Ubuntu镜像是不带着vim命令的
在这里插入图片描述
在这里插入图片描述
docker容器内执行上述两条命令:
apt-get update
apt-get -y install vim
安装完成后,commit我们自己的新镜像,下面可以看出最后成功的生成新的镜像,并且有vim

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS          PORTS                                       NAMES
3e3b091c6c42   ubuntu                   "bash"                   10 minutes ago   Up 10 minutes                                               awesome_robinson
fefe8083cf9f   ubuntu                   "bash"                   17 minutes ago   Up 17 minutes                                               dazzling_feynman
2e4c5b210b52   whyour/qinglong:2.11.3   "./docker/docker-ent…"   8 weeks ago      Up 23 minutes   0.0.0.0:8353->5700/tcp, :::8353->5700/tcp   qinglong
58e523263901   whyour/qinglong:2.11.3   "./docker/docker-ent…"   2 months ago     Up 23 minutes   0.0.0.0:8354->5700/tcp, :::8354->5700/tcp   qinglong2
[root@localhost ~]# docker commit -m="带vim的ununtu" -a="yhy" 3e3b091c6c42 vimubuntu:1.0
sha256:fe04d9dec70896d18a94108bcf0effeb75dde1fdbe3c8d8d4f10d2df55ba32a1
[root@localhost ~]# docker images
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
vimubuntu         1.0       fe04d9dec708   15 seconds ago   179MB
aero/ubuntu       1.0       6df7a1bdc1ee   22 hours ago     72.9MB
whyour/qinglong   2.11.3    124540254df2   6 months ago     497MB
redis             latest    7614ae9453d1   8 months ago     113MB
ubuntu            latest    26b77e58432b   17 months ago    72.9MB
[root@localhost ~]# docker run -it vimubuntu bash
Unable to find image 'vimubuntu:latest' locally
^Z
[1]+  已停止               docker run -it vimubuntu bash
[root@localhost ~]# docker run -it fe04d9dec708 bash
root@f81980747e05:/# vim a
root@f81980747e05:/# 

Docker容器数据卷

什么是容器数据卷

容器数据卷(Container Volumes)是用于在Docker容器和宿主机之间共享和持久化数据的一种机制。数据卷允许容器在运行时与宿主机或其他容器共享特定的文件或目录。使用容器数据卷有助于在容器停止、删除或重新创建时保留数据。

为何使用容器卷

  1. 数据的持久化,当容器重启后保证数据不丢失,例如我们可以使用卷将 MySQL 的目录持久化,实现容器重启数据库数据将不会丢失。防止手贱删掉了容器,数据不见了。

  2. 如果将数据存储于镜像中,主机上的其他进程不方便访问这些数据。

容器卷有哪些特点

  1. 数据卷可在容器之间共享或重用数据

  2. 数据卷中的更改不会包含在镜像的更新中

  3. 卷中的更改可以直接生效

  4. 数据卷的生命周期一直持续到没有容器使用它为止

宿主vs容器之间映射添加容器卷

Docker的数据管理(volume/bind mount/tmpfs)
docker存储有哪几种方式

  • Volumes方式下: 容器内的数据被存放到宿主机(linux)一个特定的目录下(/var/lib/docker/volumes/)。这个目录只有Docker可以管理,其他进程不能修改。如果想持久保存容器的应用数据,Volumes是Docker推荐的挂载方式。
  • Bind mounts方式下:容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或文件中。除了Docker之外的进程也可以任意对他们进行修改;
  • tmpfs方式下: 容器的数据只会存放到宿主机的内存中,不会被写到宿主机的文件系统中,因此不能持久保存容器的应用数据。

命令:

 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录      镜像名

案例:
新建一个容器并指定映射关系,如果容器需要别名加上--name =“别名”

docker run -it --privileged=true -v /tmp/myHostData:/tmp/myDockerData myub1 /bash

在这里插入图片描述
–privileged=true 作用:

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
 
 
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即
使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

docker inspect 容器id\名 查看是否映射成功
在这里插入图片描述
经过实验可以看出,确实是共享的
在这里插入图片描述

卷的继承和共享

在这里插入图片描述

docker run -it  --privileged=true --volumes-from 父类  --name u2 ubuntu

继承我们上面刚创建的容器,可以看出,确实是继承了
在这里插入图片描述

DockerFile

是什么

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
在这里插入图片描述
构建三步骤

  • 编写Dockerfile文件
  • docker build命令构建镜像
  • docker run依镜像运行容器实例

DockerFile构建过程解析

Dockerfile内容基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层并对镜像进行提交

Docker执行Dockerfile的大致流程
(1)docker从基础镜像运行一个容器
(2)执行一条指令并对容器作出修改
(3)执行类似docker commit的操作提交一个新的镜像层
(4)docker再基于刚提交的镜像运行一个新容器
(5)执行dockerfile中的下一条指令直到所有指令都执行完成

小总结

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

在这里插入图片描述

1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;

3 Docker容器,容器是直接提供服务的。

tomcat9的dockerfile官方链接

常用保留字指令解释

FROM

基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from

MAINTAINER

·镜像维护者的姓名和邮箱地址

RUN

RUN 指令用于在镜像构建过程中执行命令。它的作用是在当前镜像的上下文中运行给定的命令,然后将命令执行后的结果保存到新的镜像层中。

  1. Shell 形式
    • 在 shell 形式中,RUN 指令会将命令传递给容器的默认 shell 进行执行。通常,默认 shell 是 /bin/sh -c。
    • Shell 形式的命令可以使用 shell 的功能,比如通配符和环境变量扩展。
    • 例如:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
  1. Exec 形式
    • 在 exec 形式中,命令直接作为一个可执行文件执行,而不经过默认 shell。
    • 这种形式的优势之一是更好的信号处理。当使用 exec 形式时,容器能够更好地接收来自 Docker 的信号,例如docker stop时的 SIGTERM。
    • Exec 形式可以避免一些与 shell 解释器相关的问题,并且可以更容易地传递参数。
    • 例如:
FROM ubuntu:latest
RUN ["apt-get", "update", "&&", "apt-get", "install", "-y", "nginx"]

RUN 创建新的镜像层
指在 Docker 镜像构建过程中,每个 RUN 指令都会生成一个新的镜像层。这是因为 Docker 采用分层存储的机制,每个指令都会在当前基础镜像的基础上创建一个新的层,而这些层会被堆叠在一起形成最终的镜像。

每个镜像层都包含了在该层上执行的指令的结果。这使得 Docker 镜像可以被高效地构建和共享,因为如果多个镜像共享相同的层,它们只需存储一份相同的层,而不是多份冗余数据。

举个例子:

FROM ubuntu

# 第一个镜像层,安装软件包
RUN apt-get update && apt-get install -y nginx

# 第二个镜像层,创建一个文件
RUN touch /var/log/mylog.log

在上述 Dockerfile 中,有两个 RUN 指令,每个指令都会创建一个新的镜像层。第一个层包含了安装 Nginx 的结果,第二个层包含了创建 /var/log/mylog.log 文件的结果。

这种分层存储的机制使得 Docker 镜像变得轻量且易于管理。每个镜像层都是只读的,当容器运行时,Docker 会将这些只读层组合在一起,创建一个可写的容器层,该容器层负责处理容器运行时的写入操作。

阳哥推荐
用shell形式

GPT推荐
在实践中,推荐使用 exec 形式,特别是当构建的镜像可能在不同环境中运行时。这样可以避免由于不同 shell 解释器的行为差异而引起的问题,并提供更一致的行为。

当使用 shell 形式时,命令将被传递给默认 shell 进行解释,这可能导致在不同的基础镜像或操作系统中的不同行为。因此,为了最大的可移植性和一致性,建议使用 exec 形式。

EXPOSE

用于告知Docker应该打开指定的网络端口,并允许从容器外部访问

EXPOSE <port> [<port>/<protocol>...]
  • <port> : 要暴露的端口号。
  • <protocol>:(可选)指定端口使用的协议(例如,“tcp” 或 “udp”)。
    以下是带有 EXPOSE 指令的Dockerfile示例:
FROM nginx:latest

# 暴露端口80,用于HTTP
EXPOSE 80

# 其他Dockerfile指令在这里添加

在上述示例中,Dockerfile基于官方的NGINX镜像,并暴露了端口80,表示容器化的NGINX Web服务器将在端口80上可访问。

请注意,仅仅使用 EXPOSE 指令并不能将端口发布到主机。要使容器内部的暴露端口可以从容器外部访问,您需要在运行 docker run 命令时使用 -p 或 --publish 选项。例如:

docker run -p 8080:80 mynginximage

在此命令中,容器内的端口80被映射到主机上的端口8080。现在,可以使用主机的IP地址和端口8080访问容器内部的NGINX Web服务器。

WORKDIR

指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点

在构建Docker镜像时,可以使用 WORKDIR 指令来切换到指定的目录,使得接下来的命令相对于该目录执行。

USER

指定该镜像以什么样的用户去执行,如果都不指定,默认是root

ENV

用来在构建镜像过程中设置环境变量

ENV MY_PATH /usr/mytest

这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,

比如:WORKDIR $MY_PATH

COPY

COPY <src> <dest>
  • <src> 可以是本地文件或目录的路径,也可以是构建上下文中的相对路径。
  • <dest> 是目标容器中的路径,必须是绝对路径。
COPY ./app /usr/src/app

上述示例将本地的 ./app 目录复制到容器中的 /usr/src/app 目录。

ADD

ADD <src> <dest>
  • <src> 可以是本地文件或目录的路径,也可以是构建上下文中的相对路径。除此之外, 还支持URL和tar文件。
  • <dest> 是目标容器中的路径,必须是绝对路径。
ADD http://example.com/myfile.txt /usr/src/app/

在这个例子中,Docker会从http://example.com/myfile.txt下载文件,并将其复制到容器中的/usr/src/app/目录。

COPY和ADD如何选择

如果只是简单地将本地文件或目录复制到容器中,推荐使用 COPY。它的语法更简单,而且在大多数情况下足够使用。

如果需要处理远程URL、自动解压缩tar文件或复制文件并改变权限等高级功能,可以使用 ADD。

总体而言,一般情况下,推荐使用 COPY,因为它更直观且透明。只有在需要 ADD 的高级功能时才使用它

VOLUME

VOLUME ["<路径1>", "<路径2>"...]
FROM ubuntu
VOLUME ["/data"]

上述示例创建了一个卷,将宿主机的 /data 目录映射到容器内部的 /data 目录。任何在容器内 /data 目录下的数据都将持久存在,并且可以通过卷映射在宿主机上进行访问。

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

docker run -v /host/data:/data my_image

上述命令将容器内的 /data 目录映射到宿主机的 /host/data 目录。

CMD

用于指定容器启动时要执行的默认命令

Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换

例如,假设你有以下的 Dockerfile:

FROM ubuntu
CMD ["echo", "Hello, Docker!"]

当你运行容器时:

docker run my_image "Goodbye, Docker!"

“Goodbye, Docker!” 将替换 CMD 中定义的默认参数,容器启动后执行的命令会变成 echo “Goodbye, Docker!”。

这样的机制允许用户在运行容器时动态地传递参数,从而改变容器的行为。这对于根据不同的场景定制容器行为非常有用。

CMD 和 RUN 是 Dockerfile 中两个不同的指令,它们的作用和用法不同。

RUN 用于在构建时执行命令,而 CMD 用于定义容器启动时执行的默认命令。
RUN 在构建时执行,它影响镜像的静态内容。CMD 影响容器启动时的动态行为。
RUN 创建新的镜像层,而 CMD 不会。
RUN 是在构建时执行的,而 CMD 是在运行时执行的。
理解这两个指令的不同是构建 Docker 镜像时的关键,可以帮助你更好地优化镜像的大小和性能。

ENTRYPOINT

ENTRYPOINT 指令用于配置容器启动时执行的默认命令,它与 CMD 指令有些类似,但有一些关键的区别。

ENTRYPOINT ["executable", "param1", "param2", ...]
  • executable 是要执行的可执行文件或脚本。
  • param1, param2, … 是传递给 executable 的参数。

ENTRYPOINT 指令定义的命令和参数不会被用户在运行容器时提供的命令行参数所覆盖

FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
docker run my_image World

实际执行的命令是 echo Hello World。用户提供的参数 World 会被追加到 ENTRYPOINT 定义的命令之后。

这种行为使得 ENTRYPOINT 更适合定义容器的主要执行命令,而用户可以在运行容器时提供额外的参数。这样,Docker 容器就可以被看作是一个可执行的应用程序,用户只需提供必要的参数。

通过dockerfile发布微服务部署到docker容器

在这里插入图片描述

应用生成并上传

  1. 随便写个springboot服务,用上redis和mysql存储数据即可,然后打包成jar包上传到/mydocker

编写Dockerfile文件

写完上传到/mydocker,使用同一目录,ADD docker_boot-0.0.1-SNAPSHOT.jar zzyy_docker.jar命令才能找到这个jar包

# 基础镜像使用java
FROM openjdk:8
# 作者
MAINTAINER zzyy
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为zzyy_docker.jar
ADD docker_boot-0.0.1-SNAPSHOT.jar zzyy_docker.jar
# 这个命令的目的可能是为了确保 /zzyy_docker.jar 这个文件存在,即使在复杂的构建过程中,确保该文件被正确创建。在实际应用中,这样的操作可能会因为一些特殊的构建需求而存在,或者是为了确保文件的存在性,避免后续的命令因为文件不存在而出错。
RUN bash -c 'touch /zzyy_docker.jar'
#运行jar包
ENTRYPOINT ["java","-jar","/zzyy_docker.jar"]
#暴露6001端口作为微服务
EXPOSE 6001

构建镜像

docker build -t zzyy_docker:1.6 .

-t 选项后面可以指定镜像的名称和标签,格式为 name:tag。

运行容器

docker run -d -p 6001:6001 zzyy_docker:1.6

访问测试

看到容器运行,然后访问写的接口看看redis和mysql李有没有数据新增即可

[root@admin ~]# docker ps
CONTAINER ID   IMAGE             COMMAND                   CREATED        STATUS        PORTS                                                  NAMES
1ed393fb5bc9   zzyy_docker:1.6   "java -jar /zzyy_doc…"   20 hours ago   Up 20 hours   0.0.0.0:6001->6001/tcp, :::6001->6001/tcp              relaxed_rhodes
e9cb1dec8730   redis             "docker-entrypoint.s…"   21 hours ago   Up 21 hours   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp              blissful_leavitt
81d913a6a46a   mysql:5.7         "docker-entrypoint.s…"   21 hours ago   Up 21 hours   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   festive_wu

docker网络

是什么

Docker网络是Docker容器之间和容器与外部网络之间的通信和连接的一种机制。在Docker中,每个容器都可以有自己的网络栈,包括网络接口、IP地址和网络配置。Docker网络提供了一种灵活且可定制的方式,使得容器之间可以相互通信,并与主机或其他网络资源进行交互。

能做什么

Docker网络可以实现容器之间的互联以及端口映射,容器IP变动的时候可以通过服务名直接网络通信而不受影响。

当前系统网络查看

[root@admin ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:4f:2d:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.80.132/24 brd 192.168.80.255 scope global noprefixroute dynamic ens33
       valid_lft 1564sec preferred_lft 1564sec
    inet6 fe80::4f82:58f3:332e:1827/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::d9a6:d39d:e1b3:9cdc/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:aa:06:7c:0e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aaff:fe06:7c0e/64 scope link 
       valid_lft forever preferred_lft forever
9: vethb511a20@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 2a:0e:70:44:7a:74 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::280e:70ff:fe44:7a74/64 scope link 
       valid_lft forever preferred_lft forever
11: veth3cbc5d8@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether e6:79:0c:69:9b:5e brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::e479:cff:fe69:9b5e/64 scope link 
       valid_lft forever preferred_lft forever
21: veth27317bc@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether de:a8:f7:03:aa:2e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::dca8:f7ff:fe03:aa2e/64 scope link 
       valid_lft forever preferred_lft forever

lo(Loopback):
地址:127.0.0.1
IPv6 地址:::1
这是回环设备,用于本地主机通信。

ens33:

地址:192.168.80.132,子网掩码为 /24
IPv6 地址:fe80::4f82:58f3:332e:1827/64,fe80::d9a6:d39d:e1b3:9cdc/64
物理网卡 ens33 的 IP 地址信息,属于 192.168.80.0 网段。

docker0:
地址:172.17.0.1,子网掩码为 /16
IPv6 地址:fe80::42:aaff:fe06:7c0e/64
Docker 默认的网络桥接设备,Docker 容器连接到此网络。

vethb511a20@if8、veth3cbc5d8@if10、veth27317bc@if20:

这是 Docker 容器的虚拟以太网设备,连接到 Docker 桥接网络 docker0 上。
每个设备都有一个唯一的 MAC 地址,例如 link/ether 2a:0e:70:44:7a:74。
总结:你的系统有一个物理网卡 ens33,Docker 使用 docker0 作为默认网络桥接设备,而各个容器则通过虚拟以太网设备(如 vethb511a20@if8)连接到这个桥接网络。

所有命令

Docker 提供了一系列的网络命令,用于管理容器网络。以下是一些常见的 Docker 网络命令及其解释:

docker network create:
用于创建 Docker 网络。
示例:docker network create mynetwork

docker network ls:
列出所有 Docker 网络。
示例:docker network ls

docker network inspect:
显示有关一个或多个网络的详细信息。
示例:docker network inspect mynetwork

docker network rm:
从 Docker 中删除一个或多个网络。
示例:docker network rm mynetwork

docker network connect:
将容器连接到一个网络。
示例:docker network connect mynetwork mycontainer

docker network disconnect:
将容器从一个网络断开。
示例:docker network disconnect mynetwork mycontainer

docker network prune:
删除未使用的网络。
示例:docker network prune

docker network inspect:
显示一个或多个网络的详细信息。
示例:docker network inspect mynetwork

docker network create -d bridge:
创建一个桥接网络。
示例:docker network create -d bridge mybridge

docker network create -d overlay:
创建一个覆盖网络,适用于跨多个 Docker 主机的容器通信。
示例:docker network create -d overlay myoverlay

docker network create -d host:
创建一个主机网络,容器使用主机的网络栈。
示例:docker network create -d host myhost
这些命令允许你管理 Docker 中的网络,包括创建、列出、删除网络,以及将容器连接到或断开网络。

下面是例子,创建和删除网络
在这里插入图片描述

Docker 容器内部的 IP 地址是可以发生变化的

当你创建一个容器时,Docker 会自动分配一个 IP 地址给容器,这通常是在容器所属的网络范围内的一个可用地址。容器启动后,你可以使用 docker inspect 命令查看容器的详细信息,其中包括分配给容器的 IP 地址。

然而,容器的 IP 地址可能发生变化的几种情况包括:

  1. 容器重新启动: 如果容器停止并重新启动,Docker 可能会重新分配一个新的 IP 地址给容器。
  2. 容器所属网络的配置更改: 如果容器连接到一个用户定义的网络,而该网络的配置发生更改,也可能导致容器的 IP 地址发生变化。
  3. 使用动态分配的 IP 地址: 如果容器所在的网络配置为动态分配 IP 地址(例如,使用 DHCP),则容器的 IP 地址可能在每次启动时都会变化。

为了确保容器的 IP 地址对外部服务或其他容器是可预测的,可以考虑使用 Docker 的网络别名或者容器名称来代替直接使用 IP 地址。这样,无论容器的 IP 地址是否发生变化,你都可以通过别名或容器名称来访问容器。

veth 和 eth0

veth 和 eth0 是与 Docker 容器网络相关的两个概念。

veth (Virtual Ethernet): veth 是 Linux 内核中的虚拟以太网设备对。它以成对的方式出现,形成一对虚拟网卡,其中一个端口连接到宿主机的网络命名空间,另一个端口连接到容器的网络命名空间。这对虚拟网卡之间通过一个虚拟的以太网线缆(veth pair)相连,实际上是一条虚拟的网络链路,使得宿主机和容器可以进行通信。

eth0: eth0 是网络接口的命名约定,表示容器中的主要网络接口。当你在 Docker 容器中看到 eth0 时,它实际上是容器内部的网络接口,通过 veth 连接到宿主机的网络命名空间中的对应接口。

总体来说,veth 和 eth0 是容器网络实现的两个关键组成部分。veth 负责将容器的网络连接到宿主机,而 eth0 是容器内部的主要网络接口。这种结构允许容器通过 eth0 与宿主机和其他容器进行通信。

bridge

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

2.docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址

3.网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。
 3.1.整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
 3.2 每个容器实例内部也有一块网卡,每个接口叫eth0;
 3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。
通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。

示例
容器网络接口信息
在这里插入图片描述
宿主机网络接口信息
在这里插入图片描述
可以看到他们是一对一对的
宿主机的24: vethed55a21@if23 和tomcat的23: eth0@if24对应

在 vethed55a21@if23 中,ed55a21 是容器内的虚拟以太网设备的名称,而 23 是它在宿主机上的编号。这对应着容器内的网络设备 eth0@if24,其中 eth0 是容器内的以太网设备的名称,24 是这个设备在宿主机上的编号。

所以,vethed55a21@if23 和 eth0@if24 是相对应的。
宿主机的26: vethe981183@if25 和my-tomcat-copy的25: eth0@if26对应

自定义网络

在Docker中,自定义网络主要用于连接多个容器,以便它们能够相互通信。使用自定义网络有以下一些好处:

隔离性: 每个自定义网络都是独立的,这意味着在一个网络中的容器不能直接访问其他网络中的容器,除非你明确设置了路由规则。

命名解析: 容器可以通过容器名称进行通信,而不必依赖IP地址。Docker内置的DNS服务器会根据容器名称解析成相应的IP地址。

连接多个容器: 你可以将多个容器连接到同一个网络中,使它们能够方便地互相通信。这对于构建分布式应用或微服务架构非常有用。

自定义IP范围: 你可以为自定义网络指定IP地址范围,以便更好地控制容器的IP地址分配。

网络驱动: Docker支持不同的网络驱动,每个驱动提供不同的网络功能。例如,"bridge"驱动用于连接容器到主机网络,"overlay"驱动用于在多个Docker主机之间创建覆盖网络。

案例
新建一个自定义网络,然后新建俩容器加入这个网络,用容器名互ping是可以通的,如果是桥接就不行了,之鞥呢用ip才能ping通

docker network create my-network
docker run -d -p 9081:8080 --network my-network  --name tomcat81 my-tomcat
docker run -d -p 9082:8080 --network my-network  --name tomcat82 my-tomcat

在这里插入图片描述
**结论:**自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)

Docker-compose容器编排

是什么

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

作用

docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?

如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具

例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。。。。。。

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

可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。

安装

使用以下命令下载 Docker Compose:
这个命令是从 Docker Compose 的官方 GitHub 仓库的 Release 页面获取的。具体来说:

https://github.com/docker/compose/releases/latest/download/ 是 Docker Compose Release 版本的基础 URL。
docker-compose- ( u n a m e − s ) − (uname -s)- (unames)(uname -m) 是根据操作系统和架构动态生成的二进制文件名。 ( u n a m e − s ) 获取操作系统名称, (uname -s) 获取操作系统名称, (unames)获取操作系统名称,(uname -m) 获取机器架构信息。
通过这个 URL,curl 命令从 GitHub 下载了最新版本的 Docker Compose,并通过 -o 选项将其保存到 /usr/local/bin/docker-compose 文件中。这样,您可以在系统上的任何位置执行 docker-compose 命令,因为 /usr/local/bin 是系统中默认的可执行文件路径之一。

这是一种常见的从 GitHub 下载二进制文件并安装到系统路径的方法,以确保用户能够方便地使用最新版本的工具。

curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

授予执行权限:

chmod +x /usr/local/bin/docker-compose

检查是否安装成功:

docker-compose --version

常用命令

启动服务:docker-compose up

它会根据 docker-compose.yml 文件中的配置构建镜像并启动相关的容器。默认情况下,会在前台运行,使用 -d 选项可以在后台运行。

停止服务:docker-compose down

停止并移除所有相关的容器、网络和卷。使用 -v 选项可以删除关联的卷。

查询运行容器:docker-compose ps

查看服务中正在运行的容器的状态,包括容器 ID、名称、状态等信息。

查询日志:docker-compose logs

查看服务的日志。使用 -f 选项可以实时查看日志。

进入容器:docker-compose exec

在运行的服务容器中执行命令。用于进入容器内部执行一些操作,例如调试或运行特定的命令。

构建服务:docker-compose build

用于手动构建服务的镜像,通常在修改了 Dockerfile 或相关配置后使用。

拉取镜像:docker-compose pull

用于更新服务的镜像,确保使用的是最新版本。

重启服务:docker-compose restart

重新启动服务的容器,应用配置的任何更改。

停止服务:docker-compose stop

停止服务的容器,但不会删除相关的网络和卷。

启动服务:docker-compose start

启动服务的容器,用于重新启动之前停止的服务。

暂停 / 恢复服务:docker-compose pause / docker-compose unpause

暂停服务的容器,以便在不删除容器的情况下暂停其运行。

指定容器构建和重启

如果只需要重新构建 Spring Boot 容器,而不重新构建其他容器,可以按照以下步骤操作:

进入包含 Docker Compose 配置文件的目录

cd /your/docker-compose-directory

停止当前运行的 Spring Boot 容器:

docker-compose stop microService

重新构建并启动 Spring Boot 容器:

docker-compose up -d --build microService

这将重新构建 microService 容器,并以后台模式启动。

这样,你只重新构建和启动了指定的 Spring Boot 容器,而不影响其他容器。确保你的代码变动已经被正确构建到容器中。

指定配置文件启动服务

如果你的 Docker Compose 配置文件不是默认的 docker-compose.yml 文件,你可以使用 -f 或 --file 选项来指定配置文件的路径。例如:

docker-compose -f /path/to/your/docker-compose-file.yml up

在这个命令中,-f 选项后面是你的 Docker Compose 配置文件的完整路径。这样,你就可以指定不同的文件名或路径,而不仅仅是默认的 docker-compose.yml 文件。

如果你在同一目录下有多个 Compose 文件,可以使用 -f 指定多个文件:

docker-compose -f docker-compose-common.yml -f docker-compose-dev.yml up

这将合并两个配置文件的内容并运行服务。

不用Compose出现的问题

  1. 先后顺序要求固定,先mysql+redis才能微服务访问成功
  2. 多个run命令…
  3. 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产IP写死(可以但是不推荐),要么通过服务调用

使用Compose

更改springboot服务配置,通过服务名访问mysql和redis

spring.datasource.url=jdbc:mysql://mysql:3306/learn?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.redis.host=redis

构建镜像

改完配置,打包上传到/mydocker,dockerfile还是用之前的

docker build -t zzyy_docker:1.6 .

编写docker-compose.yml文件

version: "3"
 
services:
  microService:
    image: zzyy_docker:1.6
    container_name: ms01
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks: 
      - my-network 
    depends_on: 
      - redis
      - mysql
 
  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    networks: 
      - my-network
 
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'learn'
    ports:
       - "3306:3306"
    networks:
      - my-network
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
 
networks: 
   my-network: 

在后台启动容器

docker-compose up -d

进入mysql,初始化数据库和表

然后访问接口测试下就行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值