Docker学习

Docker最近用的真多

一、Docker概述

1、docker为什么会出现

工作中,经常出现“在我的机器上可正常工作”的问题

因为环境不一致等原因导致。。。

Docker的思想就来自于集装箱!

隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。

Docker通过隔离机制,可以将服务器利用到极致!

2、Docker的历史

Docker 是基于Go 语言实现的开源容器项目,诞生于2013 年年初,最初发起者是 dotCloud 公司。Docker 自开源后受到广泛的关注和l 讨论,目前已有多个相关项目(包括 Docker 三剑客、Kubemetes 等),逐渐形成了围绕Docker 容器的生态体系。 由于Docker 在业界造成的影响力实在太大, dotCloud 公司后来也直接改名为Docker Inc ,并专注于Docker 相关技术和产品的开发。

自从dotCloud公司开源其Docker项目后,凭借其便捷的Docker镜像技术解决了当时困扰众多PaaS项目的难题:如何为应用打包,让用户将本地的应用顺利迁移到PaaS平台,而不用顾忌应用的开发语言、配置、依赖包等诸多因素,也因此开启了全新的Docker容器时代。

3、Docker能干嘛

对开发和运维( DevOps )人员来说,可能最梦寐以求的效果就是一次创建或配置, 之后可以在任意地方、任意时间让应用正常运行。

具体说来, Docker 在开发和运维过程中,具有如下几个方面的优势:

  1. 更快速的交付和部署

    使用Docker ,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成之后,测试和运维人员可以直接使用完全相同环境来部署代码。只要开发测试过的代码,就可以确保在生产环境无缝运行。Docker 可以快速创建和删除容器,实现快速迭代,大量节约开发、测试、部署的时间。并且,整个过程全程可见,使团队更容易理解应用的创建和工作过程。

  2. 更高效的资源利用

    Docker 容器的运行不需要额外的虚拟化管理程序(Virtual Machine Manager, VMM ,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。跟传统虚拟机方式相比,要提高一到两个数量级。

  3. 更轻松的迁移和扩展

    Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等,同时支持主流的操作系统发行版本。这种兼容性让用户可以在不同平台之间轻松地迁移应用。

  4. 更简单的更新管理

    使用Dockerfile ,只需要小小的配置修改,就可以替代以往大量的更新工作。并且所有修改都以增量的方式被分发和更新,从而实现自动化并且高效的容器管理。

Docker 和常见的虚拟化方式的不同之处

image-20240921201222753

传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统 层。Docker 容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,因此更加 轻量级。

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多;Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。

二、Docker安装

1、Docker的基本组成

image-20240921201553913

  • 镜像(Image)

    什么是 Docker 镜像?简单的理解,Docker 镜像就是一个 Linux 的文件系统(Root FileSystem),这个文件系统里面包含可以运行在 Linux 内核的程序以及相应的数据。

    通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。

    Docker 把 App 文件打包成为一个镜像,并且采用类似多次快照的存储技术,可以实现:

    • 多个 App 可以共用相同的底层镜像(初始的操作系统镜像)
    • App 运行时的 IO 操作和镜像文件隔离
    • 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个 App 镜像可以用来运行无数个不同业务的容器
  • 容器(container)

    镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

    通俗来讲,镜像相当于类,容器相当于对象

  • 仓库(repository)

    仓库可看成一个代码控制中心,用来保存镜像。

    仓库分为公有仓库和私有仓库。(很类似git)

    Docker Hub是国外的。

    阿里云…都有容器服务器(配置镜像加速!)

2、安装docker

  • 使用云服务器的,可以直接去对应的官网寻找对应的安装配置方案
  • 比如我这里使用的就是腾讯云的Ubuntu系统
  1. 执行以下命令,添加 Docker 软件源。
1
2
3
4
5
6
7
8
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://mirrors.cloud.tencent.com/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.cloud.tencent.com/docker-ce/linux/ubuntu/ \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
  1. 执行以下命令,安装 Docker。
1
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. 执行以下命令,运行 Docker。
1
systemctl start docker
  1. 执行以下命令,检查安装结果。
1
docker info

返回如下信息,即表示安装成功。

image-20240922094005847

  • 配置对应的加速源
1
vim /etc/docker/daemon.json
  • 然后添加以下内容
1
2
3
4
5
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
]
}
  • 执行以下命令,重启 Docker 即可。
1
sudo systemctl restart docker

测试使用

运行hello-world

image-20240922095218341

查看镜像

1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d2c94e258dcb 16 months ago 13.3kB

查看容器

1
2
3
4
root@VM-16-10-ubuntu:/home/ubuntu# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e09e9f8b65 hello-world "/hello" About a minute ago Exited (0) About a minute ago compassionate_gates
# 加-a表示所有容器,包括未运行的,不加-a表示正在运行的容器

移除容器镜像

1
2
3
4
5
6
root@VM-16-10-ubuntu:/home/ubuntu# docker rmi -f d2c94e258dcb  移除镜像
Untagged: hello-world:latest
Untagged: hello-world@sha256:91fb4b041da273d5a3273b6d587d62d518300a6ad268b28628f74997b93171b2
Deleted: sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a
root@VM-16-10-ubuntu:/home/ubuntu# docker rm 03e09e9f8b65 移除容器
03e09e9f8b65

3、回滚hello-world流程

image-20240922100450374

底层原理

docker是怎么工作的

docker是一个client-server结构的系统,docker守护进程运行在主机上,然后通过socket连接从客户端访问docker守护进程。

docker守护进程从客户端接收命令,并按照命令,管理运行在主机上的容器。

一个docker容器,是一个运行时环境,可以简单理解为进程运行的集装箱。

image-20240922100554772

为什么docker比vm快

  1. Docker有这比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker上的程序直接使用的都是实际物理机上的硬件资源,因此在CPU、内存利用率上有明显的优势。
  2. **Docker利用的是宿主机的内核,而不需要使用Guest OS ** ,因此当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核,而避免引寻 ,加载操作系统内核是个比较费事费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返回的新建的过程是分钟级别,而docker直接使用的是宿主机上的操作系统,则省略了返回这个的过程,因此新建一个docker容器只需要几秒钟。

虚拟机与Docker架构对比图:

image-20240922100609249

image-20240922100613510

三、Docker常见命令

官方文档常用命令地址:https://docs.docker.com/reference/

image-20240922101137679

1、帮助命令

1
2
3
4
5
6
7
#显示docker的版本信息。
docker version
#显示docker的系统信息,包括镜像和容器的数量
docker info
#帮助命令
docker --help
docker 命令 --help

2、镜像命令

docker image 查看所有本地主机上的镜像

参数和选项

  • -a, –all 列出所有镜像
  • -q, –quiet 只显示镜像id

测试

1、查看本地主机上的镜像

1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d2c94e258dcb 16 months ago 13.3kB

解释:

  • REPOSITORY 镜像的仓库源
  • TAG 镜像的标签(版本) latest表示最新的版本
  • IMAGE ID 镜像id
  • CREATED 镜像的创建时间
  • SIZE 镜像的大小

2、列出所有镜像的id

1
2
root@VM-16-10-ubuntu:/home/ubuntu# docker images -aq
d2c94e258dcb

docker search 搜索镜像

镜像仓库地址:https://hub.docker.com/

参数和选项

  • -f, –filter filter 基于条件过滤

测试

1、搜索mysql镜像

在docker仓库上搜 https://hub.docker.com/

也可以直接使用命令去搜

1
docker search ****

不过服务器要是不太行,一般会直接超时。

1
2
root@VM-16-10-ubuntu:/home/ubuntu# docker search mysql
Error response from daemon: Get "https://index.docker.io/v1/search?q=mysql&n=25": dial tcp 199.59.150.39:443: i/o timeout

docker rmi删除镜像

1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker rmi -f 镜像id                    #删除指定镜像
root@VM-16-10-ubuntu:/home/ubuntu# docker rmi -f 镜像id1 镜像id2 镜像id3 #删除多个镜像
root@VM-16-10-ubuntu:/home/ubuntu# docker rmi -f $(docker images -aq) #删除所有镜像

3、容器命令

我们有了镜像,才能创建容器,所以先下载一个centos镜像来学习

1
2
3
4
5
6
7
root@VM-16-10-ubuntu:/home/ubuntu# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
a1d0c7532777: Pull complete
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest

启动容器

docker run [可选参数] 容器名或者容器id

创建一个新的容器并运行一个命令

可选参数

  • -i: 以交互模式运行容器,通常与 -t 同时使用
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -d: 后台运行容器,并返回容器ID;
  • –name=”nginx-lb”: 为容器指定一个名称
  • -e username=”ritchie”: 设置环境变量

测试:

1、使用镜像centos以交互模式启动一个容器,在容器内执行/bin/bash命令

1
2
root@VM-16-10-ubuntu:/home/ubuntu# docker run -it centos /bin/bash
[root@5bfd7775d62f /]#
1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bfd7775d62f centos "/bin/bash" 55 seconds ago Up 54 seconds goofy_ellis

退出容器

1
2
exit       #直接退出容器并关闭
快捷键:ctrl+p+q #容器不关闭退出 注意p和q的顺序!

列出所有的容器

docker ps

可选参数

  • **-a :**显示所有的容器,包括未运行的。
  • **-n :**列出最近创建的n个容器。
  • **-q :**静默模式,只显示容器编号。
1
2
3
4
5
6
7
8
root@VM-16-10-ubuntu:/home/ubuntu# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bfd7775d62f centos "/bin/bash" About a minute ago Up About a minute goofy_ellis
root@VM-16-10-ubuntu:/home/ubuntu# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bfd7775d62f centos "/bin/bash" About a minute ago Up About a minute goofy_ellis
8d2482707137 hello-world "/hello" 12 minutes ago Exited (0) 12 minutes ago clever_mccarthy
root@VM-16-10-ubuntu:/home/ubuntu#

删除容器

1
2
3
docker rm -f 容器id                       # 删除指定容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm -f # 删除所有的容器

启动和停止容器

1
2
3
4
docker start 容器id           # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前的容器

4、常用其他命令

后台启动命令

1
2
3
4
5
6
7
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d centos
3c59ba355924fa7659dea00b40ee81e0b156ea8173cc3ed55d10abdda9b71346
root@VM-16-10-ubuntu:/home/ubuntu# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

# 问题,后端启动容器后,docker ps,发现centos停止了
# 常见的坑, docker 容器使用后台运行, 就必须要有一个前台进程,docker发现没有应用,就会自动停止
1
2
3
4
5
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d -it centos  #这种启动容器后就不会关闭了
427021a3fe1bed3ce5a2950d50204b0b5c7ba6124e436132cb810791e04d7c9d
root@VM-16-10-ubuntu:/home/ubuntu# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427021a3fe1b centos "/bin/bash" 3 seconds ago Up 3 seconds brave_moore

查看日志

docker logs [参数与参选] 容器id

参数与选项

  • -f : 跟踪日志输出
  • -t : 显示时间戳
  • **–since :**显示某个开始时间的所有日志
  • -n或者**–tail :**仅列出最新N条容器日志
1
2
3
4
5
6
7
8
# docker logs -tf -n=10 容器id
root@VM-16-10-ubuntu:/home/ubuntu# docker logs -tf -n=10 427021a3fe1b
# 这里没有日志,我们自己编写一段shell脚本
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d -it centos /bin/bash -c "while true;do echo zyy hello;sleep 10;done"
26805bf07f643d921b05be3a9c3f9eff41481bc302406c8c64b8ffbfc72b52ee
root@VM-16-10-ubuntu:/home/ubuntu# docker logs -tf -n=10 26805bf07f6
2024-09-22T02:29:02.878255691Z zyy hello
2024-09-22T02:29:12.896589927Z zyy hello

命令docker run -d -it centos /bin/bash -c "while true;do echo zyy hello;sleep 1;done"解释:

该命令会不停地输出字符串 “zyy hello”,每隔 1 秒钟输出一次,直到容器被停止。

其中,各个参数的含义如下:

  • docker run 是 Docker 命令的基本语法,用于启动一个新的容器。
  • -d 参数表示在后台运行容器。
  • centos 参数表示使用的镜像名称,这里使用的是 CentOS 镜像。
  • /bin/bash -c "while true;do echo zyy hello;sleep 1;done" 参数表示在容器内部执行的 shell 命令。其中 /bin/bash 是 shell 的路径,-c 参数表示在 shell 中执行指定的命令。这里的命令是一个无限循环,不停地输出字符串 “zyy hello”。

查看容器中的进程信息

docker top 容器id

1
2
3
4
5
6
root@VM-16-10-ubuntu:/home/ubuntu# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ee256515d6e centos "/bin/bash" 4 seconds ago Up 3 seconds frosty_swartz
root@VM-16-10-ubuntu:/home/ubuntu# docker top 4ee256515d6e
UID PID PPID C STIME TTY TIME CMD
root 2564662 2564639 0 10:33 pts/0 00:00:00 /bin/bash

查看镜像的元数据

docker inspect 容器id
元数据 (meta data)——“data about data” 描述数据的数据,一般是结构化数据

元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名,版本、出版数据、相关说明,包括检索点等),用于组织、描述、检索、保存、管理信息和知识资源

1
2
3
4
5
6
7
8
9
10
root@VM-16-10-ubuntu:/home/ubuntu# docker inspect 4ee256515d6e
[
{
"Id": "4ee256515d6e776f4e2b6e8e80d1a65b67635347465ba27a08035cffb3f01983",
"Created": "2024-09-22T02:33:02.5872125Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
........

进入当前正在运行的容器

方式一:docker exec

docker exec -it 容器id /bin/bash

1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker exec -it 4ee256515d6e /bin/sh
sh-4.4# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

方式二:docker attach

docker attach 容器id

1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker attach 4ee256515d6e
[root@4ee256515d6e /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

区别

1
2
# docker exec       # 进入容器后开启一个新的终端,可以在里面操作
# docker attach # 进入容器正在执行的终端,不会启动新的进程

从容器拷贝到主机上、从主机拷贝到容器上

docker cp 容器id:容器文件 主机路径

docker cp 主机文件 容器id:容器路径

5、命令大全

https://pythondjango.cn/python/tools/2-docker-dockerfile/

image-20240922104456381

四、Docker的使用练习

1、Docker安装nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@VM-16-10-ubuntu:/home/ubuntu# docker pull nginx 1、 拉取nginx
Using default tag: latest
latest: Pulling from library/nginx
a2318d6c47ec: Pull complete
095d327c79ae: Pull complete
bbfaa25db775: Pull complete
7bb6fb0cfb2b: Pull complete
0723edc10c17: Pull complete
24b3fdc4d1e3: Pull complete
3122471704d5: Pull complete
Digest: sha256:04ba374043ccd2fc5c593885c0eacddebabd5ca375f9323666f28dfd5a9710e3
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
root@VM-16-10-ubuntu:/home/ubuntu# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 39286ab8a5e1 5 weeks ago 188MB
hello-world latest d2c94e258dcb 16 months ago 13.3kB
centos latest 5d0da3dc9764 3 years ago 231MB
root@VM-16-10-ubuntu:/home/ubuntu# docker run -it -d --name nginx01 -p 3344:80 nginx 启动nginx
6c511e58320a06a81eeec1708d7fecd85486d8b879711ab3993e6599849cb5d6
root@VM-16-10-ubuntu:/home/ubuntu# docker ps 查看nginx容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c511e58320a nginx "/docker-entrypoint.…" 28 seconds ago Up 28 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01

image-20240922105436716

成功搭建(注意这里需要服务器开启对应的3344端口,外界才能访问到)

docker run -it -d --name nginx02 -p 3344:80 nginx解释

  • docker run:启动一个新的容器
  • -it:表示启用交互式终端并分配一个伪终端,这样我们可以在容器中交互式地执行命令。
  • -d:表示将容器运行在后台(守护进程)。
  • --name nginx02:给容器起一个名字叫做 nginx02
  • -p 3344:80:将主机的 3344 端口映射到容器的 80 端口,这样我们就可以通过主机的 3344 端口来访问容器内的 Nginx 服务。
  • nginx:表示要启动的镜像名称为 nginx

因此,这个命令的作用是在 Docker 中启动一个名为 nginx02 的容器,运行 Nginx 服务,并将容器的 80 端口映射到主机的 3344 端口,以便我们可以通过访问主机的 3344 端口来访问 Nginx 服务。容器会在后台运行,并启用交互式终端。

2、安装一个tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@VM-16-10-ubuntu:/home/ubuntu# docker pull tomcat  拉取镜像
Using default tag: latest
latest: Pulling from library/tomcat
32b824d45c61: Pull complete
fe18bb7e114f: Pull complete
581ebfe08d3f: Pull complete
7c7bdd063feb: Pull complete
28f1e2918031: Pull complete
dbce9ebf04f0: Pull complete
4f4fb700ef54: Pull complete
2963b9c3d96f: Pull complete
Digest: sha256:0298f25ea8171042fe610457ff0fd72382d36a144eae4483e2784bbbae31d68b
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d -p 3355:8080 --name tomcat01 tomcat 启动容器
c0186e2559f5fe67ca6b32f386859ea1a3028572c42c93237ef746581c59361e

image-20240922110708559

发现服务可以访问,但是没有页面

进入服务

1
2
root@VM-16-10-ubuntu:/home/ubuntu# docker exec -it c0186e2559 /bin/bash 进入容器
root@c0186e2559f5:/usr/local/tomcat/webapps# ls

发现webapp下为空

1
2
# 原因:阿里云镜像的原因,阿里云默认是最小的镜像,所以不必要的都剔除掉
# 保证最小可运行的环境!

解决方案:将webapps.dist下的文件都拷贝到webapps下即可

1
root@c0186e2559f5:/usr/local/tomcat# cp -r webapps.dist/* webapps

刷新一下服务,就有页面了

image-20240922111002319

问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,比如webapps,我们在外部放置项目,就自动同步内部就好了!

3、Docker安装Elesticsearch

elasticsearch暴露的端口很多

十分耗内存(所以体现测试的时候可以提前把其他docker容器先停止,启动时可以限制堆内存大小)

es 的数据一般需要放置到安全目录!挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
Unable to find image 'elasticsearch:7.6.2' locally
7.6.2: Pulling from library/elasticsearch
ab5ef0e58194: Pull complete
c4d1ca5c8a25: Pull complete
941a3cc8e7b8: Pull complete
43ec483d9618: Pull complete
c486fd200684: Pull complete
1b960df074b2: Pull complete
1719d48d6823: Pull complete
Digest: sha256:1b09dbd93085a1e7bca34830e77d2981521a7210e11f11eda997add1c12711fa
Status: Downloaded newer image for elasticsearch:7.6.2
6861a387a1cac6856d948d54b5ec3db63b04f762d0deb2a7f7ba4e77af3d7a62
root@VM-16-10-ubuntu:/home/ubuntu# curl localhost:9200
{
"name" : "6861a387a1ca",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "b2Wz4EljT7qCteo0VMyFMQ",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
1
2
3
root@VM-16-10-ubuntu:/home/ubuntu# docker stats   #查看cpu状态
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
6861a387a1ca es 3.26% 368.8MiB / 1.918GiB 18.78% 4.11kB / 3.75kB 6.16MB / 2.03MB 45

image-20240922112744309

docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2命令解释

这是一个使用 Docker 命令行工具来启动一个 Elasticsearch 版本为 7.6.2 的容器,并设置了一些选项和参数。

具体来说,这些选项和参数的含义如下:

  • -d 表示在后台运行容器,即以“守护进程”模式运行,不会占用当前终端的控制台;
  • --name es 表示给容器起一个名称为 “es”;
  • -p 9200:9200 -p 9300:9300 表示将容器内部的 9200 端口和 9300 端口映射到主机的 9200 和 9300 端口上,以便在主机上通过浏览器或客户端连接 Elasticsearch;
  • -e "discovery.type=single-node" 表示设置 Elasticsearch 的节点类型为 “single-node”,即单节点模式,这是一个简单的运行 Elasticsearch 的方式,适用于测试或开发环境;
  • -e ES_JAVA_OPTS="-Xms64m -Xmx512m" 表示设置 Elasticsearch 的 Java 虚拟机参数,其中 “-Xms64m” 表示设置初始堆大小为 64MB,”-Xmx512m” 表示设置最大堆大小为 512MB;
  • elasticsearch:7.6.2 表示要运行的容器镜像名称和版本号,这里是 Elasticsearch 官方提供的 7.6.2 版本。

总体来说,这个命令的作用是在 Docker 中启动一个 Elasticsearch 7.6.2 的容器,并将容器内部的端口映射到主机上,以便在主机上访问 Elasticsearch。其中的选项和参数可以根据需要进行修改或调整。

五、portainer可视化面板安装

  • portainer(先用这个)
  • rancher(CI/DI再用)
1
2
3
4
5
6
7
8
9
10
root@VM-16-10-ubuntu:/home/ubuntu# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Unable to find image 'portainer/portainer:latest' locally
latest: Pulling from portainer/portainer
772227786281: Pull complete
96fd13befc87: Pull complete
0bad1d247b5b: Pull complete
b5d1b01b1d39: Pull complete
Digest: sha256:47b064434edf437badf7337e516e07f64477485c8ecc663ddabbe824b20c672d
Status: Downloaded newer image for portainer/portainer:latest
8de613bef9cc0af508c8db2433789ee570f1a7737260130c36ab03d7fcfd54a9

docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer解释

这是一个用于运行 Docker 容器的 Docker 命令。具体来说,该命令启动了一个名为 Portainer 的 Docker 容器,并将容器的 9000 端口映射到主机的 8088 端口,以便在主机上通过浏览器访问 Portainer。

以下是各个参数的含义:

  • -d:表示以后台模式运行容器。
  • -p 8088:9000:表示将容器的 9000 端口映射到主机的 8088 端口。
  • --restart=always:表示容器在停止后总是会自动重启。
  • -v /var/run/docker.sock:/var/run/docker.sock:表示将主机的 Docker 守护进程的 Unix 套接字文件(/var/run/docker.sock)挂载到容器的同一位置,从而让 Portainer 可以管理主机上的其他 Docker 容器。
  • --privileged=true:表示在容器中开启特权模式,以便 Portainer 能够访问主机上的 Docker 守护进程。

总之,这个命令的作用是在主机上启动一个 Portainer 容器,以便通过 web 界面来管理和监控其他 Docker 容器。

image-20240922151045620

image-20240922151150791

image-20240922151227485

  • 使用图形化界面对docker容器镜像进行对应的管理

六、Docker镜像

1、镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含

运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

2、Docker镜像加载原理

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,

它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系

统下(unite several directories into a single virtual fifilesystem)。Union 文件系统是 Docker 镜像的基

础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件

系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot fifile system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启

动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是

一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已

由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root fifile system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标

准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

image-20240922152448693

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

image-20240922152528402

对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直

接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一

致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

3、分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@VM-16-10-ubuntu:/home/ubuntu# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
a2318d6c47ec: Pull complete
ed7fd66f27f2: Pull complete
410a3d5b3155: Pull complete
9312cf3f6b3e: Pull complete
c39877ab23d0: Pull complete
01394ffc7248: Pull complete
4f4fb700ef54: Pull complete
5a03cb6163ab: Pull complete
Digest: sha256:eadf354977d428e347d93046bb1a5569d701e8deb68f090215534a99dbcb23b9
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest

思考:为什么Docker镜像要采用这种分层的结构呢?

最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机

只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服

务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker image inspect 命令!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:8e2ab394fabf557b00041a8f080b10b4e91c7027b7c174f095332c7ebb6501cb",
"sha256:9a978e3d8066b448323af0ea471da443c1e9da9dd8d0663d380b6af6a5ef14ed",
"sha256:a64e92ee12394b08486442cb272116d6b0a4f363748434316a2e9ed2fdd379c0",
"sha256:40710ab1222c055362a531507662df6177a4a2c97095b5ead8389c1e5b797615",
"sha256:15ef09f0323042ab4d842cd2d5d53d1cdd99414ee787d08f7d7064bf69d2d146",
"sha256:e4dbf0bd9d9df4561e608086d426c8edca8dd2fd9b83b2bc76b4fbc88066fc1d",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:950a085c0a1cd3e27102081e4a7bfb4bd0a624325b1cd3caf71f0d5f5eced6b6"
]
},

理解:

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之

上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果

在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就

会创建第三个镜像层。

该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

image-20240922152707544

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件

7 是文件 5 的一个更新版本。

image-20240922152716981

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新

镜像层添加到镜像当中。

Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统

一的文件系统。

Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储

引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker 在 Windows 上仅支持 windowsfifilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分

层和 CoW。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20240922152734675

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

4、镜像commit

docker commit 从容器创建一个新的镜像。

1
2
3
4
docker commit 提交容器副本使之成为一个新的镜像!

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

实际操作

1
2
3
4
5
6
7
8
9
10
root@VM-16-10-ubuntu:/home/ubuntu# docker run -it -p 3355:8080 --name tomcat01 tomcat  启动tomcat
root@c8e254e9555b:/usr/local/tomcat# cp -r webapps.dist/* webapps 进行tomcat的修改
root@VM-16-10-ubuntu:/home/ubuntu# docker commit -a="6pc1" -m="add webapps tomcat" c8e254e9555b mytomcat:1.0 将新的容器提交
sha256:c4cc1b3de0ff0849bccb0dffa83397f0a6ff1af3a4907bca933856a5da04745a
root@VM-16-10-ubuntu:/home/ubuntu# docker images 成功提交对应镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 c4cc1b3de0ff 13 seconds ago 474MB
tomcat latest 7f14c7d5cf60 4 days ago 469MB
redis latest 590b81f2fea1 7 weeks ago 117MB
centos latest 5d0da3dc9764 3 years ago 231MB

如果你想要保存你当前的状态,可以通过commit,来提交镜像,方便使用,类似于 VM 中的快照!

七、容器数据卷

1、什么是容器数据卷

docker的理念回顾:

将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够

持久化的!

就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成

新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行

不通的!

为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除

而丢失了!

作用:

卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此

能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂

载的数据卷

特点:

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

2、使用容器数据卷

方式一:容器中直接使用命令来添加

挂载

1
2
3
4
命令
# docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名
测试
# docker run -it -v /home/test:/home centos /bin/bash

查看数据卷是否挂载成功docker inspect 容器id

image-20240922162754059

测试容器和宿主机之间数据共享:可以发现,在容器中,创建的会在宿主机中看到!

测试容器停止退出后,主机修改数据是否会同步!

  1. 停止容器
  2. 在宿主机上修改文件
  3. 启动刚才停止的容器
  4. 然后查看对应的文件,发现数据依旧同步

实战:使用docker安装mysql

思考:mysql 数据持久化的问题!

  1. 下载镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    root@VM-16-10-ubuntu:/home/ubuntu# docker pull mysql:5.7
    5.7: Pulling from library/mysql
    20e4dcae4c69: Pull complete
    1c56c3d4ce74: Pull complete
    e9f03a1c24ce: Pull complete
    68c3898c2015: Pull complete
    6b95a940e7b6: Pull complete
    90986bb8de6e: Pull complete
    ae71319cb779: Pull complete
    ffc89e9dfd88: Pull complete
    43d05e938198: Pull complete
    064b2d298fba: Pull complete
    df9a4d85569b: Pull complete
    Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
    Status: Downloaded newer image for mysql:5.7
    docker.io/library/mysql:5.7
  2. 启动容器

    1
    root@VM-16-10-ubuntu:/home/ubuntu# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
  3. 可以成功同步对应的信息,使用mysql连接工具就可以变相直接控制docker内的数据库了

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7命名解释

这个命令使用 Docker 运行 MySQL 5.7 容器,并做出以下配置:

  • -d 表示容器在后台运行(即“守护进程”模式)。
  • -p 3310:3306 将容器内的 MySQL 端口 3306 映射到主机的端口 3310 上,这样你就可以通过主机上的端口 3310 访问 MySQL 服务。
  • -v /home/mysql/conf:/etc/mysql/conf.d 将主机上的目录 /home/mysql/conf 挂载到容器的 /etc/mysql/conf.d 目录中,这样你可以在主机上编辑 MySQL 配置文件,并且它们会在容器内生效。
  • -v /home/mysql/data:/var/lib/mysql 将主机上的目录 /home/mysql/data 挂载到容器的 /var/lib/mysql 目录中,这样你可以在主机上保存 MySQL 数据文件,并且它们会在容器内生效。
  • -e MYSQL_ROOT_PASSWORD=123456 设置 MySQL root 用户的密码为 123456
  • --name mysql01 指定容器的名称为 mysql01,以便于管理和查找。
  • mysql:5.7 指定使用官方提供的 MySQL 5.7 镜像。

这个命令的作用是在 Docker 中创建并运行一个 MySQL 容器,同时将主机上的目录挂载到容器中,以便于配置和保存数据。

3、匿名和具名挂载

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

4、初识Dockerfile

DockerFile 是用来构建Docker镜像的构建文件,是由一些列命令和参数构成的脚本。

我们在这里,先体验下,后面我们会详细讲解 DockerFile !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#1.进入宿主机目录,在目录下再创建一个目录docker-test-volume,在这个新建目录下新建一个文件dockerfile
root@VM-16-10-ubuntu:/home/ubuntu/test# mkdir docker-test-volumn
root@VM-16-10-ubuntu:/home/ubuntu/test# cd docker-test-volumn/

#2.编辑dockerfile1这个文件
#说明:在编写DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷
#出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在 DockerFile中实现
#由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# vim dockerfile
FROM centos
VOLUME ["volume1","volume2"]
CMD echo "-----end-----"
CMD /bin/bash

#3.build后生成镜像,获得一个新镜像 my-centos
#注意最后有一个.
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# docker build -t my-centos .
[+] Building 0.3s (5/5) FINISHED docker:default
=> [internal] load build definition from dockerfile 0.0s
=> => transferring dockerfile: 123B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/1] FROM docker.io/library/centos:latest 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:f0839ab2b921916360f89feb21d60cec317c13b76274d4c6de29d9d6bb404f52 0.0s
=> => naming to docker.io/library/my-centos 0.0s
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 c4cc1b3de0ff About an hour ago 474MB
tomcat latest 7f14c7d5cf60 4 days ago 469MB
redis latest 590b81f2fea1 7 weeks ago 117MB
mysql 5.7 5107333e08a8 9 months ago 501MB
my-centos latest f0839ab2b921 3 years ago 231MB
centos latest 5d0da3dc9764 3 years ago 231MB

#4.启动容器 发现数据卷目录volume1和volume2
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# docker run -it f0839ab2b921 /bin/bash
[root@20aafb95c23c /]# ls
bin etc lib lost+found mnt proc run srv tmp var volumn2
dev home lib64 media opt root sbin sys usr volumn1
#5.进入容器,进入volume1目录,1.txt文件,然后退出容器
[root@20aafb95c23c /]# cd volumn1
[root@20aafb95c23c volumn1]# ls
[root@20aafb95c23c volumn1]# touch 1.txt
[root@20aafb95c23c volumn1]# ls
1.txt
[root@20aafb95c23c volumn1]# exit
exit
#问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢?
#6.查看容器信息
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20aafb95c23c f0839ab2b921 "/bin/bash" About a minute ago Exited (0) 23 seconds ago busy_greider
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volumn# docker inspect f0839ab2b921

image-20240922170917802

1
2
3
4
#8、发现宿主机文件
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# cd /var/lib/docker/volumes/5408b9e55fc0210903273841542b6fdb1cf0e3e1286994f19d08db8c78c6963b/_data
root@VM-16-10-ubuntu:/var/lib/docker/volumes/5408b9e55fc0210903273841542b6fdb1cf0e3e1286994f19d08db8c78c6963b/_data# ls
1.txt

注意:如果访问出现了 cannot open directory: Permission denied

解决办法:在挂载目录后多加一个 –privileged=true参数即可

5、数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为

数据卷容器。

我们使用上一步的镜像:my-centos 为模板,运行容器 docker01,docker02,docker03,他

们都会具有容器卷volume1和volume2

我们来测试下,容器间传递共享

  1. 用my-centos镜像,启动容器docker01,在volume2目录下新建一个文件from_docker01.txt

    1
    2
    3
    4
    5
    root@VM-16-10-ubuntu:/home/ubuntu# docker run -it --name docker01 my-centos
    [root@a31ad75c98e6 /]# cd volume2
    [root@a31ad75c98e6 volume2]# touch from_docker01.txt
    [root@a31ad75c98e6 volume2]# ls
    from_docker01.txt
  2. 退出不停止容器:ctrl+p+q

    1
    2
    3
    # root@VM-16-10-ubuntu:/home/ubuntu# docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    a31ad75c98e6 my-centos "/bin/sh -c /bin/bash" About a minute ago Up About a minute docker01
  3. 用my-centos镜像,启动容器docker02,让docker02继承docker01 --volumes-from

    在volume2目录下新建一个文件from_docker02.txt

    1
    2
    3
    4
    root@VM-16-10-ubuntu:/home/ubuntu# docker run -it --name docker02 --volumes-from docker01 my-centos
    [root@de7b3fc3cf53 /]# cd volume2
    [root@de7b3fc3cf53 volume2]# ls
    from_docker01.txt

容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本机的文件则会一直保留!

八、dockerfile

大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?

我们要研究自己如何做一个镜像,而且我们写的微服务项目以及springboot打包上云部署,Docker就是

最方便的。

微服务打包成镜像,任何装了Docker的地方,都可以下载使用,极其的方便。

流程:开发应用=>DockerFile=>打包为镜像=>上传到仓库(私有仓库,公有仓库)=> 下载镜像 => 启动

运行。

还可以方便移植!

1、什么是dockerfile

dockerfifile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

构建步骤:

  1. 编写DockerFile文件
  2. docker build 构建镜像
  3. docker run

dockerfifile文件我们刚才已经编写过了一次,这里我们继续使用 centos 来看!

https://hub.docker.com/_/centos

image-20240922172857074

2、dockerfile的构建过程

基础知识

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

流程:

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

说明:

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

  • DockerFile 是软件的原材料 (代码)
  • Docker 镜像则是软件的交付品 (.apk)
  • Docker 容器则是软件的运行状态 (客户下载安装执行)

DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!

image-20240922173620477

DockerFile:需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容

包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进

程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权

限控制)等等。

Docker镜像:在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行

Docker 镜像时,会真正开始提供服务;

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

3、Dockerfile指令

关键字:

1
2
3
4
5
6
7
8
9
10
11
12
FROM        # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER # maintainer 镜像维护者的姓名和邮箱地址
RUN # 容器构建时需要运行的命令
EXPOSE # 当前容器对外暴露出的端口
WORKDIR # 指定在创建容器后,终端默认登录进来的工作目录,一个落脚点
ENV # 用来在构建镜像过程中设置环境变量
ADD # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY # 类似ADD,拷贝文件和目录到镜像中!但是是不会自动解压文件,也不能访问网络资源
VLIUME # 容器数据卷,用于数据保存和持久化工作
CMD # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最 后一个生效!
ENTRYPOINT # entrypoint 指定一个容器启动时要运行的命令!和CMD一样 可以追加命令
ONBUILD # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发

image-20240923190649837

4、实战测试

Docker Hub 中99% 的镜像都是通过在base镜像(Scratch)中安装和配置需要的软件构建出来的

image-20240923190944663

自定一个centos镜像

  1. 编写dockerfile

    直接运行centos的官方镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# docker run -it centos /bin/bash
    Unable to find image 'centos:latest' locally
    latest: Pulling from library/centos
    a1d0c7532777: Already exists
    Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
    Status: Downloaded newer image for centos:latest
    [root@bcf6eb6bf82f /]# vim a
    bash: vim: command not found
    [root@bcf6eb6bf82f /]# ifconfig
    bash: ifconfig: command not found

    发现,不支持vim和ifconfig命令,登陆后的默认路径是/

    目的:使我们自己的镜像具备如下:登陆后的默认路径、vim编辑器、查看网络配置ifconfifig支持

    准备编写DockerFlie文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# vim mydockerfile-centos
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# cat mydockerfile-centos
    FROM centos
    MAINTATINER 6pc1<pc6pc1@qq.com>

    ENV MYPATH /usr/local
    WORKDIR $MYPATH

    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim

    RUN yun -y install net-tools

    EXPOSE 80

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

    说明:dockerfile中直接RUN yum -y install vim可能会报下面错误

    1
    #0 1.607 Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist

    说明下面这些,其实就是为了让RUN yum -y install vim可以执行成功

    1
    2
    3
    4
    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim
  2. 构建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# docker build -f mydockerfile-centos -t mycentos:1.0 .
    [+] Building 4.3s (11/11) FINISHED docker:default
    => [internal] load build definition from mydockerfile-centos 0.0s
    => => transferring dockerfile: 452B 0.0s
    => [internal] load metadata for docker.io/library/centos:latest 0.0s
    => [internal] load .dockerignore 0.0s
    => => transferring context: 2B 0.0s
    => [1/7] FROM docker.io/library/centos:latest 0.0s
    => CACHED [2/7] WORKDIR /usr/local 0.0s
    => CACHED [3/7] RUN cd /etc/yum.repos.d/ 0.0s
    => CACHED [4/7] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* 0.0s
    => CACHED [5/7] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum 0.0s
    => CACHED [6/7] RUN yum -y install vim 0.0s
    => [7/7] RUN yum -y install net-tools 3.4s
    => exporting to image 0.8s
    => => exporting layers 0.8s
    => => writing image sha256:c3dec9b6a3f811c4d5e5038392822da54ab5e069560708059a1f8bc636eca32d 0.0s
    => => naming to docker.io/library/mycentos:1.0
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    mycentos 1.0 c3dec9b6a3f8 30 seconds ago 312MB
    centos latest 5d0da3dc9764 3 years ago 231MB

    命令:docker build -f mydockerfile-centos -t mycentos:1.0 .解释:

    这是一个Docker命令,将使用指定的Dockerfile构建一个新的Docker镜像。

    具体来说,该命令的各个部分的含义如下:

    • docker build:使用Docker命令构建新的镜像
    • -f mydockerfile-centos:指定Dockerfile的名称为mydockerfile-centos。默认情况下,Docker使用当前目录下的名为Dockerfile的文件作为Dockerfile,但是在这里我们指定了一个不同的名称。
    • -t mycentos:1.0:指定构建的镜像名称为mycentos,标签为1.0。标签可用于标识同一镜像的不同版本或变体。
    • .:指定上下文路径,即构建过程中所使用的文件路径。这里的.表示使用当前目录作为上下文路径。

    因此,该命令的含义是使用mydockerfile-centos文件作为Dockerfile,将当前目录下的文件作为上下文构建一个名为mycentos、标签为1.0的新Docker镜像。

  3. 运行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# docker run -it mycentos:1.0
    [root@391dcbf08c75 local]# pwd
    /usr/local
    [root@391dcbf08c75 local]# ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
    ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
    RX packets 9 bytes 806 (806.0 B)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 0 bytes 0 (0.0 B)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
    inet 127.0.0.1 netmask 255.0.0.0
    inet6 ::1 prefixlen 128 scopeid 0x10<host>
    loop txqueuelen 1000 (Local Loopback)
    RX packets 0 bytes 0 (0.0 B)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 0 bytes 0 (0.0 B)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    [root@391dcbf08c75 local]# vim a
    [root@391dcbf08c75 local]# ls
    a bin etc games include lib lib64 libexec sbin share src
  4. 列出镜像的历史

    docker history 镜像id

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume# docker history c3dec9b6a3f8
    IMAGE CREATED CREATED BY SIZE COMMENT
    c3dec9b6a3f8 5 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
    <missing> 5 minutes ago CMD ["/bin/sh" "-c" "echo \"----end------\""] 0B buildkit.dockerfile.v0
    <missing> 5 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
    <missing> 5 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
    <missing> 5 minutes ago RUN /bin/sh -c yum -y install net-tools # bu… 14.7MB buildkit.dockerfile.v0
    <missing> 6 minutes ago RUN /bin/sh -c yum -y install vim # buildkit 66.3MB buildkit.dockerfile.v0
    <missing> 6 minutes ago RUN /bin/sh -c sed -i 's|#baseurl=http://mir… 8.8kB buildkit.dockerfile.v0
    <missing> 6 minutes ago RUN /bin/sh -c sed -i 's/mirrorlist/#mirrorl… 8.82kB buildkit.dockerfile.v0
    <missing> 6 minutes ago RUN /bin/sh -c cd /etc/yum.repos.d/ # buildk… 0B buildkit.dockerfile.v0
    <missing> 6 minutes ago WORKDIR /usr/local 0B buildkit.dockerfile.v0
    <missing> 6 minutes ago ENV MYPATH=/usr/local 0B buildkit.dockerfile.v0
    <missing> 6 minutes ago MAINTAINER 6pc1<pc6pc1@qq.com> 0B buildkit.dockerfile.v0
    <missing> 3 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
    <missing> 3 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
    <missing> 3 years ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB

CMD和ENTRYPOINT的去呗

我们之前说过,两个命令都是指定一个容器启动时要运行的命令

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

替换!

ENTRYPOINT:docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

自定义镜像tomcat

  1. 新建一个路径,并准备好tomcat和jdk的压缩包(官网下载后本地上传到服务器),并新建一个read.txt、新建一个Dockfile文件,并编辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# cat Dockerfile 
    FROM centos

    MAINTAINER 6pc1<pc6pc1@qq.com>

    COPY 1.txt /usr/local/read.txt

    ADD apache-tomcat-9.0.95.tar /usr/local/
    ADD jdk-8u202-linux-x64.tar /usr/local/

    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim

    ENV MYPATH /usr/local

    WORKDIR $MYPATH

    ENV JAVA_HOME /usr/local/jdk_1.8.0_202
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.95
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.95
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

    EXPOSE 8080

    CMD /usr/local/apache-tomcat-9.0.95/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.95/bin/logs/catalina.out
  2. 构建镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker build -t diytomcat .
    [+] Building 146.5s (14/14) FINISHED docker:default
    => [internal] load build definition from Dockerfile 0.0s
    => => transferring dockerfile: 866B 0.0s
    => [internal] load metadata for docker.io/library/centos:latest 0.0s
    => [internal] load .dockerignore 0.0s
    => => transferring context: 2B 0.0s
    => CACHED [1/9] FROM docker.io/library/centos:latest 0.0s
    => [internal] load build context 2.5s
    => => transferring context: 206.81MB 2.5s
    => [2/9] COPY 1.txt /usr/local/read.txt 0.3s
    => [3/9] ADD apache-tomcat-9.0.95.tar.gz /usr/local/ 0.4s
    => [4/9] ADD jdk-8u202-linux-x64.tar.gz /usr/local/ 4.1s
    => [5/9] RUN cd /etc/yum.repos.d/ 0.7s
    => [6/9] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* 0.3s
    => [7/9] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos. 0.4s
    => [8/9] RUN yum -y install vim 134.1s
    => [9/9] WORKDIR /usr/local 0.1s
    => exporting to image 3.3s
    => => exporting layers 3.2s
    => => writing image sha256:88021913b4f29d54ed2453c16e79d7259ab5414f3dc616c6d4e98ca6dad90743 0.0s
    => => naming to docker.io/library/diytomcat
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    diytomcat latest 88021913b4f2 34 seconds ago 718MB
    mycentos 1.0 c3dec9b6a3f8 59 minutes ago 312MB
    centos latest 5d0da3dc9764 3 years ago 231MB
  3. 启动容器

    1
    2
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker run -d -p 9090:8080 --name mydiytomcat -v /home/ubuntu/test/docker-test-volume/tomcat/test:/usr/local/apache-tomcat-9.0.95/webapps/test diytomcat
    99f621377dba54b318e382d8f72a16ddf321888392d27b5772e1a7eeb3b1fadf
  4. 结合前面学习的容器卷将测试的web服务test发布

    WEB-INF下新建一个web.xml

    web.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?xml version="1.0" encoding="UTF-8"?>

    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">

    <display-name>test</display-name>

    </web-app>

    在test下新建一个a.jsp

    a.jsp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>hello,kuangshen</title>
    </head>
    <body>
    -----------welcome------------
    <%=" my docker tomcat "%>
    <br>
    <br>
    <% System.out.println("-------my docker tomcat-------");%>
    </body>
    </html>

5、发布镜像

DockerHub(不建议,大概率登录超时感觉)

  1. 注册dockerhub https://hub.docker.com/,注册一个账号

image-20240923204922044

  1. 登录
  2. docker push直接push到仓库中,记得加tag

腾讯云镜像服务

  1. 使用个人免费版仓库

    这要注意,只有个别地方才能选择个人免费版仓库,这边我选择的是广州

  2. 创建命名空间和仓库

    image-20240925165555292

  3. 直接快捷指令就能将容器上传至仓库了

    image-20240925165713786

1
2
3
4
5
6
7
root@VM-16-10-ubuntu:/home/ubuntu# docker login ccr.ccs.tencentyun.com --username=100036351621
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

6、总结

image-20240925183039622

九、Docker网络

1、理解docker0

准备工作:清空所有的容器,清空所有的镜像

1
2
docker rm -f $(docker ps -a -q)    # 删除所有容器 
docker rmi -f $(docker images -qa) # 删除全部镜像

先做个测试–现象

  1. 制作一个可以使用ip addrping命令的镜像(已经支持的,可以忽略这个步骤)

    下载tomcat原生镜像并启动tomcat容器tomcat01

    1
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker run -d -P --name tomcat01 tomcat

    查看容器tomcat01内部的ip地址,发现报错如下:

    1
    2
    3
    4
    5
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker exec -it tomcat01 ip addr
    OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker exec -it tomcat01 /bin/bash
    \\root@fb4000629c55:/usr/local/tomcat# ip addr
    bash: ip: command not found

    进入容器执行命令,即可解决

    1
    apt update && apt install -y iproute2

    在容器tomcat01ping一下,发现报错如下

    1
    2
    root@fb4000629c55:/usr/local/tomcat# ping 172.17.0.2
    bash: ping: command not found

    进入容器执行命令,即可解决

    1
    apt-get update && apt-get install -y iputils-ping

    容器执行了上面两个命令后,就可以正常使用ip addrping这两个命令了,然后我们把容器commit一下,就有个一个新的镜像了

    1
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker commit fb4000629c55 my-tomcat01:1.0
  2. 查看一下主机本地的ip 地址ip addr

    • lo 本机回环地址

    • eth0 阿里云的私有ip

    • docker0 docker网桥

    image-20240925185532091

  3. 启动容器tomcat01,查看一下容器的ip,然后再查一下主机本地ip

    docker会给每个容器都分配一个ip

    image-20240925185336056

  4. 我们再起一个容器,结果能够发现两个容器之间是能够ping通的

    1
    2
    3
    4
    5
    6
    root@fb4000629c55:/usr/local/tomcat# ping 172.17.0.3
    PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
    64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.099 ms
    64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.067 ms
    64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.064 ms
    64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.060 ms

原理

  1. 每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair

    技术!

  2. 每启动一个容器,linux主机就会多了一个虚拟网卡。

    veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。

    正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!

image-20240925185927195

结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动

默认都是docker0网络。

docker默认会给容器分配一个可用ip。

小结

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据

Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网

关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接

通信。

image-20240925185950744

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并

让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中

进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容

器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们

能不能使用服务名访问呢?

jdbc:mysql://mysql:3306,这样的话哪怕mysql重启,我们也不需要修改配置了!docker提供了 –link

的操作!

原理

单纯是修改了host文件使容器名指向了对应的ip地址

从而可以直接访问对应的容器名

–link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式

3、自定义网络

基本命令查看

命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network --help

Usage: docker network COMMAND

Manage networks

Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

查看所有网络

1
2
3
4
5
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network ls
NETWORK ID NAME DRIVER SCOPE
6ebce816547d bridge bridge local
05ae65613256 host host local
e0876b8be916 none null local

所有网络模式

网络模式 配置 说明
bridge模式 –net=bridge 默认值,在Docker网桥docker0上为容器创建新的网络栈
none模式 –net=none 不配置网络,用户可以稍后进入容器,自行配置
container模式 –net=container:name/id 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace
host模式 –net=host 容器和宿主机共享Network namespace
用户自定义模式 –net=自定义网络 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络

查看一个具体的网络的详情

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network inspect 6ebce816547d
[
{
"Name": "bridge",
"Id": "6ebce816547d589207a8b545c4a79bb1f3f0f4219a3794b08e2669c97f2c52f8",
"Created": "2024-09-21T20:29:18.36204997+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]

拓展:

  • 172.17.0.0/16 是一个 CIDR 地址,其中 /16 表示子网掩码的位数,即 255.255.0.0。这个地址范围内的 IP 地址数量是 2^16 - 2 = 65534。其中,2^16 表示该地址范围内的 IP 地址总数,而减去 2 是因为该地址范围内的第一个 IP 地址是网络地址,最后一个 IP 地址是广播地址,不能使用
  • 172.17.0.0/24 是一个 CIDR 地址,其中 /24 表示子网掩码的位数,即 255.255.255.0。这个地址范围内的 IP 地址数量是 2^8 - 2 = 254。其中,2^8 表示该地址范围内的 IP 地址总数,而减去 2 是因为该地址范围内的第一个 IP 地址是网络地址,最后一个 IP 地址是广播地址,不能使用。

自定义网卡

  1. 删除原来的所有的容器(这样干净一点)

    这样网络就恢复最初的样子了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 52:54:00:58:5e:1a brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 10.0.16.10/22 metric 100 brd 10.0.19.255 scope global eth0
    valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe58:5e1a/64 scope link
    valid_lft forever preferred_lft forever
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:99:03:57:1b 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:99ff:fe03:571b/64 scope link
    valid_lft forever preferred_lft forever
  2. 自定义网络

    查看命令使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    # 自定义一个网络
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network create --driver bridge --subnet 192.17.0.0/16 --gateway 192.17.0.1 mynet
    ecef3e6ceef718e93c001b8068e0c824086046e1e5196b050fab6ef65a8903b9
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network ls
    NETWORK ID NAME DRIVER SCOPE
    6ebce816547d bridge bridge local
    05ae65613256 host host local
    ecef3e6ceef7 mynet bridge local
    e0876b8be916 none null local
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network inspect mynet
    [
    {
    "Name": "mynet",
    "Id": "ecef3e6ceef718e93c001b8068e0c824086046e1e5196b050fab6ef65a8903b9",
    "Created": "2024-09-25T19:29:21.684869939+08:00",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
    "Driver": "default",
    "Options": {},
    "Config": [
    {
    "Subnet": "192.17.0.0/16",
    "Gateway": "192.17.0.1"
    }
    ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
    "Network": ""
    },
    "ConfigOnly": false,
    "Containers": {},
    "Options": {},
    "Labels": {}
    }
    ]
  3. 基于自定义网络启动容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 使用自定义网络
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker run -d -P --name tomcat-net-1 --net mynet my-tomcat01:1.0
    # 发现已经成功使用上
    root@VM-16-10-ubuntu:/home/ubuntu/test/docker-test-volume/tomcat# docker network inspect mynet
    },
    "ConfigOnly": false,
    "Containers": {
    "6ccd4eceb20ec77000793369ee924106f698c236e48f53e082b0cbd830289b13": {
    "Name": "tomcat-net-1",
    "EndpointID": "cf8a18045268e43e29e3e7ae2315af57a58560860f8fe9ce64c5f015c599dc17",
    "MacAddress": "02:42:c0:11:00:02",
    "IPv4Address": "192.17.0.2/16",
    "IPv6Address": ""
    }
    },

  4. 发现,我们自定义的网络docker都已经帮我们维护好了对应的关系

    所以我们平时都可以这样使用网络,不使用–link效果一样,所有东西实时维护好,直接域名 ping 通。

4、网络连通

  1. 启动两个容器(默认,基于docker0的网络)

    启动两个容器(默认,基于docker0的网络)

  2. 使用network connect 命令连接

    1
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network connect mynet tomcat-1
  3. 再次验证,通了

  4. 看一下tomcat-1的网络信息(tomcat01拥有了双ip)

  5. 再看一下mynet的网络信息

结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连接

十、Docker compose

Compose 是用于定义和运行多容器 Docker 应用程序的工具。

通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序

中文文档:http://www.dockerinfo.net/docker-compose-%e9%a1%b9%e7%9b%ae

官方文档:https://docs.docker.com/compose/

compose安装 要注意和Docker同一个版本

这里有独立版和插件版两种,区别感觉不大,主要就是命令的使用的一点点差别,我这主要使用的是独立版

Compose 独立版

请注意,Compose standalone 使用-compose语法 而不是当前标准语法compose
例如,docker-compose up使用 Compose standalone 时输入 ,而不是docker compose up

  1. 要下载并安装 Compose 独立版,请运行:

    1
    $ curl -SL https://github.com/docker/compose/releases/download/v2.29.6/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
  2. 将可执行权限应用于安装目标路径中的独立二进制文件。

  3. 使用 测试并执行撰写命令docker-compose

    提示

    如果安装后命令docker-compose失败,请检查您的路径。您还可以创建指向或路径中任何其他目录的符号链接/usr/bin。例如:

    $ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

compose使用

1、设置

  1. 为项目创建目录:

    1
    2
    $ mkdir composetest
    $ cd composetest
  2. 在您的项目目录中创建一个名为的文件app.py并粘贴以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import time

    import redis
    from flask import Flask

    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)

    def get_hit_count():
    retries = 5
    while True:
    try:
    return cache.incr('hits')
    except redis.exceptions.ConnectionError as exc:
    if retries == 0:
    raise exc
    retries -= 1
    time.sleep(0.5)

    @app.route('/')
    def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

    在此示例中,是应用程序网络上的 redis 容器的主机名,并使用redis默认端口。6379

    笔记

    请注意函数的编写方式get_hit_count。如果 Redis 服务不可用,此基本重试循环会多次尝试请求。这在应用程序上线时启动时很有用,但如果在应用程序的生命周期内需要随时重新启动 Redis 服务,也会使应用程序更具弹性。在集群中,这也有助于处理节点之间的瞬时连接断开。

  3. 在您的项目目录中创建另一个名为的文件requirements.txt并粘贴以下代码:

    1
    2
    flask
    redis
  4. 创建一个Dockerfile并粘贴以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # syntax=docker/dockerfile:1
    FROM python:3.10-alpine
    WORKDIR /code
    ENV FLASK_APP=app.py
    ENV FLASK_RUN_HOST=0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers
    COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt
    EXPOSE 5000
    COPY . .
    CMD ["flask", "run", "--debug"]

    重要的

    检查Dockerfile文件扩展名是否为.txt。某些编辑器可能会自动附加此文件扩展名,从而导致运行应用程序时出现错误。

2、在Compose文件中定义服务

Compose 简化了整个应用程序堆栈的控制,使您可以轻松地在单个易于理解的 YAML 配置文件中管理服务、网络和卷。

在您的项目目录中创建一个名为的文件compose.yaml并粘贴以下内容:

1
2
3
4
5
6
7
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"

该Compose文件定义了两个服务:webredis

web服务使用从当前目录中构建的镜像Dockerfile。然后它将容器和主机绑定到公开端口。8000此示例服务使用 Flask Web 服务器的默认端口5000

redis服务使用 从 Docker Hub 注册表中提取的公共Redis映像。

3、使用 Compose 构建并运行您的应用

使用单个命令,您可以从配置文件创建并启动所有服务。

  1. 从您的项目目录中,通过运行启动您的应用程序docker compose up。、
  2. 每访问一次网站,次数应该都会增加