本教程针对的是linux环境下的docker
Docker简介
什么是Docker
Docker是一个开源的容器化平台,旨在简化应用程序的开发、交付和运行
它允许开发者将应用程序及其所有依赖项打包到一个轻量级的、可移植的容器中,从而确保在不同环境中都能一致地运行
容器之间是隔离的,像一个个小型的沙箱
一句话:Docker就像一个轻量级虚拟机,可以在不同的环境中快速部署运行同样的应用程序
Docker的主要概念
容器(Container)
容器是Docker的核心,它就像是一个隔离的小程序环境,打包了应用运行所需的一切
与传统虚拟机相比,容器不需要包含整个操作系统,只共享宿主机内核,因此占用资源小、启动速度快
无论在本地、测试环境,还是部署到服务器,运行结果都一致
每个容器互相隔离,修改不会影响宿主机或其他容器
比如,运行一个Python应用的容器,就像在一个只包含Python的迷你Linux系统里运行它
镜像(Image)
镜像是构建容器的模板或快照,可以理解为包含了系统环境+应用程序代码+配置的“包”
镜像一经创建就不变,部署更可靠
比如我们下载nginx这个镜像,然后就能启动一个nginx容器,就像虚拟机的快照和启动运行
即使我们更改了容器,镜像也不会改变,我们也可以把改动的容器制作为新的镜像,类似拍摄快照
一个镜像可以启动成多个容器,就像一个类能被实例化成多个对象
Dockerfile
它是用来构建镜像的配置脚本
里面写入了构建命令,如基于哪个镜像、复制哪些文件、安装哪些软件等
使用docker build命令可以将Dockerfile构建成镜像,然后启动对应的容器
仓库(Registry)
存储和分发镜像的平台
比如DockerHub,就是Docker官方提供的镜像仓库平台(类似GitHub),有很多官方镜像可以免费下载
systemctl命令使用
systemctl是现代Linux发行版中核心的系统和服务管理器
它负责启动、停止、检查和管理系统上的各种后台服务(也称为守护进程)
在使用任何Docker命令之前,必须确保Docker的后台服务正在运行
接下来我们将以Docker服务为例结合介绍它的各种命令
服务的生命周期管理
这是 systemctl最核心的功能,用于控制一个服务的运行、停止和重启等
启动服务
当一个服务处于停止状态时,使用start命令来启动它
systemctl start 服务名称
eg:
systemctl start docker
此命令会启动Docker服务,Docker守护进程会在后台开始运行,准备接收和处理Docker相关的命令
通常执行此类操作需要管理员权限
停止服务
停止一个正在运行的服务
systemctl stop 服务名称
eg:
systemctl stop docker
此命令会向Docker服务发送停止信号,使其安全地终止
对于Docker来说,这意味着Docker守护进程会关闭,所有通过该守护进程运行的容器也会停止
重启服务
这是一个便捷的组合命令,相当于先停止服务再立即启动它
这在修改了服务的配置文件后,需要让新配置生效时非常有用
systemctl restart 服务名称
eg:
systemctl restart docker
如果修改了Docker的配置文件(例如 /etc/docker/daemon.json),执行此命令会重启 Docker 服务,使其加载并应用新的配置
重新加载服务配置
在不中断服务的情况下,重新加载其配置文件
systemctl reload 服务名称
eg:
systemctl reload docker
这个命令比restart更为温和,它会请求服务重新读取其配置文件,而不会终止正在运行的主进程
但是,并非所有服务都支持reload操作,如果服务不支持此操作,systemctl可能会转而执行restart
Docker服务通常建议使用restart而不是reload来应用配置更改
服务的状态与信息查看
查看服务详细状态
获取一个服务的全面信息,包括它是否正在运行、最近的日志、进程ID (PID) 等
systemctl status 服务名称
eg:
systemctl status docker
这是排查服务问题的首选
它会清晰地显示服务的active状态,如 active (running) 或 inactive (dead)),并附带最近几条相关的日志记录
检查服务是否正在运行
快速检查一个服务当前是否处于活动状态
systemctl is-active 服务名称
eg:
systemctl is-active docker
此命令的返回值非常简洁:
如果服务正在运行,它会输出active并返回状态码 0
如果服务未运行,它会输出inactive
这在编写自动化脚本时很有用,可以根据返回值来判断是否需要执行某些操作
服务的开机自启动管理
设置开机自启动
将一个服务设置为在系统启动时自动运行
systemctl enable 服务名称
eg:
systemctl enable docker
执行此命令后,systemd会创建必要的符号链接,确保下次系统启动时,Docker服务会自动启动
这是一个一次性的设置,之后无需再手动启动
禁止开机自启动
取消一个服务的开机自启动设置
systemctl disable 服务名称
eg:
systemctl disable docker
此命令会移除enable命令创建的符号链接,下次系统重启后,Docker服务将不会自动运行
这并不会影响当前正在运行的服务状态
检查服务是否开机自启动
查看一个服务当前是否被设置为开机自启动
systemctl is-enabled 服务名称
eg:
systemctl is-enabled docker
此命令会返回 enabled (已设置) 或 disabled (未设置)
Docker更改源
不知道为什么国内忽然无法访问官方的镜像仓库了,为了加快Docker镜像的下载速度,我们通常需要将 Docker的默认源registry.docker.io更换为国内的镜像加速源
检查安装状态
首先要确认你的系统已正确安装了Docker,可以执行:
docker --version
返回的是docker版本,确认无误后继续
编辑配置文件
Docker 的镜像源配置文件通常位于/etc/docker/daemon.json,如果文件不存在,可以手动创建
使用任意文本编辑器打开,例如使用vim(不知道怎么使用vim的可以看一眼:vim使用教程 ):
vim /etc/docker/daemon.json
然后将内容修改为以下格式:
{
"registry-mirrors": [
"https://<加速地址1>",
"https://<加速地址2>"
]
}
当然你还能添加更多加速地址,但是注意最后一个加速地址后面就不能有逗号了
b站up:大海资源整理的当前可用的国内镜像源:https://www.dhzy.fun/archives/6852.html
重启服务
修改完配置后,需要重启 Docker 服务以使配置生效:
systemctl restart docker
验证是否生效
可以执行如下命令查看当前镜像加速器配置是否生效:
docker info | grep -A 10 "Registry Mirrors"
从输出中查找包含Registry Mirrors的那一行,并显示它后面10行
如果是下面这样的输出,说明配置成功了:
注意事项
修改配置文件时要确保JSON格式正确,例如逗号不能多不能少
有些加速源如阿里云需要登录账号并绑定使用,获取专属地址
如果使用的是非systemd系统,要使用service命令重启Docker
Docker使用
镜像管理
查找镜像
docker search <镜像名称>
docker search使用的是DockerHub的HTTP API,没有镜像源概念,无法走国内加速
如果无法访问,必须使用代理,或者通过别的方式访问官网:https://hub.docker.com/
拉取镜像
从仓库中下载一个镜像到你的本地机器
docker pull <镜像名称>:<标签>
-
镜像名称:想要下载的软件,例如
nginx -
标签 :通常用来表示软件的版本,例如
latest表示最新版,1.21表示特定版本 如果省略标签,Docker 会默认使用
latest
eg:
docker pull nginx:latest
此命令会从镜像源下载最新版本的Nginx镜像
查看本地镜像
列出所有已经下载到本地计算机上的镜像
docker images
-
REPOSITORY:仓库名
-
TAG :标签
-
IMAGE ID:镜像的唯一ID
-
CREATED:创建时间
-
SIZE:镜像大小
保存更改的镜像
docker commit [选项] <容器ID>/<容器名称> <镜像名称>:<标签>
常用选项:
-
-m "提交信息":为此次操作添加描述性说明类似于 Git 的 commit message,便于记录修改内容
-
-a "作者":指定作者信息方便追踪是谁进行了修改或创建操作
eg:
docker commit -m="update" -a="kakahuote" 8950b5741b30 mynginx:mod
这个命令会执行以下操作:
- 把名为
8950b5741b30的容器保存为一个新的镜像 - 添加说明信息
"update",记录镜像的更改内容 - 指定作者为
kakahuote - 创建一个名为
mynginx、标签为mod的新镜像
删除镜像
当某个镜像不再需要时,可以将其从本地删除以释放磁盘空间
docker rmi <镜像ID>/<镜像名称>:<标签>
只能删除没有被任何容器(包括已停止的容器)使用的镜像
如果需要删除一个被使用的镜像,必须先删除所有依赖它的容器
也可以使用-f选项强制删除,但这可能会导致依赖该镜像的容器无法再次启动或者其他未知错误,慎用!
如果不指定标签,默认删除的会是latest标签,如果没有latest则会报错,所以建议指定标签删除
eg:
docker rmi mynginx:mod
容器管理
创建并运行容器
docker run [选项] <镜像名称>:<标签>
常用选项:
-
--name:为容器指定一个自定义的名称如果省略,Docker会自动生成一个随机名称
-
-d:以分离模式在后台运行容器这对于运行像Web服务器这样的长期服务很重要,否则容器会占据你的终端进行输出和报错等行为
-
-P(大写):将容器内部所有暴露的端口随机映射到主机的空闲端口上 -
-p(小写):指定端口映射,其常用格式如下:-
主机端口:容器端口docker run -d -p 8080:80 nginx此命令将主机的
8080端口映射到容器的80端口 -
<IP地址>:主机端口:容器端口指定只将主机的特定IP地址的端口映射到容器
docker run -d -p 127.0.0.1:8081:80 nginx此命令将主机
127.0.0.1这个回环地址的8081端口映射到容器的80端口这样,只有在本机才能通过
127.0.0.1:8081访问,来自外部网络的访问会被拒绝 -
主机端口:<容器端口/协议默认情况下,端口映射使用的是TCP协议,也可以显式指定UDP协议
Pdocker run -d -p 8082:53/udp nginx此命令将主机的
8082端口映射到nginx容器的53UDP端口
-
-
--rm:使容器在停止后被自动删除适合用于测试和运行一次性任务
eg:
docker run --name my-nginx -d -p 8080:80 nginx
这个命令会执行以下操作:
-
检查本地是否存在
nginx:latest镜像,如果不存在,会自动拉取 -
基于此镜像创建一个名为
my-nginx的容器 -
-d:让这个容器在后台持续运行 -
-p 8080:80:将你本机的8080端口的流量转发到容器内部的80端口(Nginx默认在80端口监听)
命令执行后,在浏览器中访问http://你的主机IP地址:8080或http://localhost:8080
如果看到Nginx的欢迎页面,则表示容器已成功运行
查看正在运行的容器
docker ps
-
CONTAINER ID:容器的唯一标识,可以用全部或者前几位操作该容器,只要能唯一识别
-
IMAGE:使用的镜像
-
COMMAND:容器启动时运行的命令
-
CREATED:容器创建的时间
-
STATUS:容器状态,这里的字段值是
UP,说明是一个正在运行的容器 -
PORTS:端口映射
-
0.0.0.0:8080->80/tcp:主机所有IPv4地址的8080端口被映射到容器内部的80端口(TCP 协议) -
:::8080->80/tcp:主机所有IPv6地址的8080端口也映射到容器内部的80端口(TCP 协议)
-
-
NAMES:自定义的容器的名字
查看所有容器
docker ps -a
-a是all的缩写,代表列出所有容器,包括那些已经停止运行的
这个命令可以找到旧的、已停止的容器,以便重新启动它们或将它们删除以进行清理
这里的STATUS字段是exited,说明这是一个退出的、不在运行的容器
停止容器
docker stop <容器名称>/<容器ID>
说明: 此命令会向容器内的主进程发送一个 SIGTERM 信号,请求其正常关闭。应用程序会接收到这个信号并执行关闭前的清理工作。
eg:
docker stop nginx
停止后,容器不在运行列表之中
启动一个已停止的容器
docker start <容器名称>/<容器ID>
这个命令会使一个处于Exited状态的容器恢复到Up状态,容器会保留其上次停止时的所有配置和数据。
示例: docker start my-nginx
删除容器
docker rm <容器名称>/<容器ID>
默认情况下,不能删除一个正在运行的容器,必须先使用docker stop将其停止
如果确定要删除一个运行中的容器,可以添加-f参数来强制执行
容器信息查看与交互
查看端口映射
此命令可以快捷地查看一个容器的端口映射情况
docker port <容器名称>/<容器ID>
eg:
docker port nginx
容器内部的80端口被映射到了:
0.0.0.0:8080:表示主机的所有IPv4地址上的8080端口[::]:8080:表示主机的所有IPv6地址上的8080端口
也就是说,我们可以使用以下任意方式访问这个容器内的Nginx服务:
http://localhost:8080http://127.0.0.1:8080http://<主机的IP>:8080- 如果启用了IPv6网络,还可以使用IPv6地址访问,如
http://[::1]:8080
查看容器日志
docker logs [选项] <容器名称>/<容器ID>
常用选项:
-
-f:持续跟踪并输出日志 -
--tail:仅显示日志的最后N行
eg:
docker logs nginx
在容器内部执行命令
可以在一个运行中的容器内执行命令,而不进入其交互式Shell
docker exec <容器名称>/<容器ID> <命令>
eg:
docker exec nginx ls -l
此命令会在名为nginx的容器内部执行ls -l 命令,并返回结果,而我们的终端仍然停留在主机上
进入容器的交互式终端
对于更复杂的调试,我们就需要一个完整的Shell环境来在容器内部进行操作
docker exec -it <容器名称>/<容器ID> /bin/bash
-it是两个选项的组合:
-i保持标准输入开启,-t分配一个伪终端,这共同创建了一个可以交互的命令行界面
/bin/bash是一个常见的Shell程序,有些镜像可能提供的是/bin/sh,比较不好用
也可以在创建容器的时候就进入其交互式终端:
docker run -it <镜像名称>:<标签> /bin/bash
eg:
docker exec -it nginx /bin/bash
执行后命令提示符改变,表示已经进入了容器,可以像在普通Linux环境中一样运行命令
如果想要退出,可以使用Ctrl+D,或者输入exit
容器网络与连接
除了端口映射,Docker还提供了强大的网络功能,允许容器之间方便、安全地互相通信
在开始之前,我们需要知道docker的网络类型有哪些
网络类型
bridge
bridge是Docker默认的网络类型,适用于单个主机上容器之间的通信
- 每个容器会获得一个虚拟网卡和私有IP地址
- 容器之间可以通过容器名通信
- 可以使用
-p参数将容器端口映射到宿主机端口,实现外部访问 - 默认的
bridge网络名称就是bridge
适用于需要隔离、但仍允许访问外部网络的容器场景
host
容器与宿主机共享网络栈,不做任何隔离
- 容器没有自己的IP地址
- 使用宿主机的IP和端口
- 性能更好,网络开销低
- 容器中暴露的端口不需要通过
-p映射
适用于对网络性能要求极高的场景
none
容器没有网络连接
- 没有分配IP地址
- 不能访问外部网络,也不能与其他容器通信
- 除非手动配置网络,否则容器完全断网
适用于需要自定义网络配置或完全隔离网络的场景
overlay
用于Docker Swarm集群环境中,支持多主机容器通信
- 可跨宿主机连接容器
- 基于VXLAN技术封装
- 需要Swarm模式支持
适用于需要将多个 Docker 主机上的容器连接成一个网络的分布式应用
macvlan
让容器像宿主机一样,直接拥有局域网内的独立IP
- 容器像物理主机一样直接连接到物理网络
- 容器具有独立MAC和IP地址
- 可被局域网中的其他设备直接访问
适用于容器需要与局域网设备完全对等通信的场景,例如作为局域网服务节点
container
多个容器共享同一个网络命名空间,通过--network container:<容器名>实现
- 使用另一个容器的网络配置
- 容器之间通过进程间通信
适用于容器需要共享网络堆栈(如日志、监控)的情况
查看当前已创建的网络
docker network ls
-
NETWORK ID:网络的唯一标识
-
NAME:网络名称
-
DRIVER:网络类型
-
SCOPE:作用范围,通常是local(本地网络)或swarm(集群网络)
创建自定义网络
docker network create -d bridge <网络名称>
-d:指定网络类型。对于单机环境,bridge是最常用的类型
eg:
docker network create -d bridge my-net
删除已定义的网络
docker network rm <网络名>/<网络ID>
eg:
docker network rm my-net
连接容器到网络
我们可以在启动容器时使用--network选项将其连接到指定的网络
docker run -d --name <容器名称> --network <网络名称> <镜像名称>
eg:
我们创建两个容器并都连接到my-net网络
首先创建第一个容器 nginx-1:
docker run -d --name nginx-1 --network my-net nginx
然后创建第二个容器 nginx-2:
docker run -d --name nginx-2 --network my-net nginx
容器间通信
当多个容器连接到同一个自定义网络时,它们可以通过容器名称作为主机名直接互相访问
我们可以进入一个容器来测试与另一个容器的连通性
eg:
进入nginx-1容器,然后ping nginx-2
docker exec -it nginx-1 /bin/bash
进入容器后,由于nginx镜像默认没有 ping 工具,我们需要先安装它:
apt-get update && apt-get install -y iputils-ping
安装完成后,执行ping:
ping nginx-2
可以看到,nginx-1能够成功解析nginx-2的名称并与之通信,这证明了容器间的互联已经建立shell
查看容器网络信息
docker inspect <对象ID或名称>
docker inspect是一个非常强大的命令,用于查看容器、镜像、网络、卷等对象的详细底层信息
它会返回一段JSON 格式的数据,包含几乎所有属性,比如网络配置、挂载卷、环境变量、启动命令等
这里我们查看容器的信息,并过滤网络部分:
docker inspect <容器ID>/<名称> | grep -A 10 "NetworkSettings"
DNS配置
全局配置
我们可以为所有Docker容器配置默认的DNS服务器
这需要在Docker的守护进程配置文件/etc/docker/daemon.json中添加dns字段
{
"dns": [
"114.114.114.114",
"8.8.8.8"
]
}
修改此文件后,必须重启 Docker 服务才能生效
容器独立配置
如果只想为某个特定的容器指定 DNS,可以在docker run时使用相关选项
docker run [DNS选项] <镜像名称>
常用DNS选项:
--dns=<IP地址>:指定容器使用的DNS服务器地址--dns-search=<域名>:指定DNS搜索域。当查找一个短主机名时,会自动追加这个域名进行尝试--hostname=<主机名>:设置容器内部的主机名
eg:
docker run -it --rm --hostname=myhost --dns=114.114.114.114 nginx
这个命令会启动一个临时的nginx容器,其主机名为myhost,使用114.114.114.114作为DNS服务器
常用DNS服务器
阿里云公共 DNS
223.5.5.5
223.6.6.6
114 DNS(国内知名公共 DNS)
114.114.114.114
114.114.115.115
Google 公共 DNS
8.8.8.8
8.8.4.4
Cloudflare DNS
1.1.1.1
1.0.0.1
OpenDNS
208.67.222.222
208.67.220.220
Docker实例安装
各种镜像安装过程都大差不差,这里以nginx为例,其他的也能作参考
查看可用版本
访问Nginx镜像库地址
https://hub.docker.com/_/nginx?tab=tags
可以copy的字段是拉取当前版本镜像的命令,下面是一些介绍:
| 字段 | 含义 |
|---|---|
| Digest | 每个平台构建出的镜像唯一标识符 |
| OS/ARCH | 表示支持的操作系统和架构 |
| Vulnerabilities | 镜像中检测出的安全漏洞数量 分等级:严重(红)、高(橙)、中(黄)、低(灰) |
| Compressed size | 镜像下载时的压缩大小 |
使用命令查看
docker search nginx
我们一般都使用最新的,也就是latest
拉取最新镜像
docker pull nginx:latest
查看是否拉取成功
docker images
运行容器
docker run --name nginx -p 8080:80 -d nginx
参数说明:
- –name nginx:容器名称改成nginx
- -p 8080:80: 端口进行映射,将本地8080端口映射到容器内部的80端口
- -d:设置容器在在后台一直运行
测试访问
http://localhost:8080