文章目录
- 一、什么是容器?
- 二、为什么需要容器
- 三、容器的生命周期
- 容器状态
- 容器OOM
- 容器异常退出
- 容器异常退出
- 容器暂停
- 四、容器命令
- 命令清单
- 详细介绍
- 五、容器操作案例
- 容器的状态迁移
- 容器批量操作
- 容器交互模式
- attached 模式
- detached 模式
- interactive 模式
- 容器 与 宿主机 文件拷贝
- 容器 自动删除 与 自动重启
- 容器环境变量设置
- 查看容器的详细信息
- 容器镜像的导入导出
- 镜像的资源查看
- 镜像的日志查看
- 容器的资源查看
- 六、综合实战
- Mysql 容器化安装
- Redis 容器化安装
- Redis 出现的原因
- Redis 是什么
- Redis 的应用场景
- C++ 容器制作
- 容器资源更新
一、什么是容器?
首先,我们了解了镜像,容器可以被视为镜像的实际运行实例。镜像本身是一个静态且只读的文件,而容器则在此基础上附加了一个可写的文件层,这使得容器能够运行需要的进程。简单来说,容器是运行着实际应用进程的实体。
容器有五种基本状态:创建、运行、停止、暂停和删除。
容器本质上是主机上一个运行的进程,但它通过独立的命名空间隔离和资源限制与主机进程区分开来。在容器内部,无法直接访问主机上的进程、环境变量或网络等信息,这也是容器与直接在主机上运行的进程之间的关键区别。
容器是基于镜像创建的可执行实例,且可以独立存在。一个镜像可以启动多个容器实例。容器化环境的运行实质上是在容器内创建一个文件系统的读写副本,也就是说,为镜像添加了一层新的容器层,这一层允许对镜像副本进行修改。
镜像和容器的关系就像:一个类实例化出多个对象,而这几个对象的差别却很大;
当然,容器的差别主要体现在它们的运行时状态上(比如不同容器内的文件更改、配置或进程等)
二、为什么需要容器
我们知道,镜像是静态的文件,其自身并不能提供服务,类似一个Windows、Linux的光驱,需要在主机上才能运行;
同理,真正的应用环境在容器中运行。
下面再简单列举一下 为什么需要容器:
-
轻量级虚拟化:容器比传统虚拟机更轻便,占用资源少,启动更快。
-
环境隔离:每个容器都提供独立的运行环境,避免应用之间的环境冲突。
-
一致的开发、测试和生产环境:容器保证在不同环境中应用的运行一致性,解决“在我电脑上能跑”的问题。
-
高效的资源利用:容器共享宿主操作系统的内核,减少资源浪费,相比虚拟机能运行更多实例。
-
快速启动和部署:容器启动速度快,通常在几秒钟内即可启动,适用于快速部署和动态伸缩。
-
简化运维管理:容器化应用易于管理、迁移和扩展,便于自动化部署和持续集成。
三、容器的生命周期
容器状态
类比进程的生命周期,容器的生命周期一样与其运行状态相关,容器有以下五种运行状态:
- created:初建状态
- running:运行状态
- stopped:停止状态
- paused:暂停状态
- deleted:删除状态
各生命周期之间的转换关系如图所示:
我们可以通过下面命令,对容器进行操作并将容器转为不同的状态:
-
docker create
创建容器后,不立即启动运行,容器进入初建状态。 -
docker run
创建容器,并立即启动运行,进入运行状态。 -
docker start
容器转为运行状态。 -
docker stop
容器将转入停止状态。 -
docker kill
容器在故障(死机)时执行kill
(断电),容器转入停止状态。
这种操作容易丢失数据,除非必要,否则不建议使用。 -
docker restart
重启容器,容器转入运行状态。 -
docker pause
容器进入暂停状态。 -
docker unpause
取消暂停状态,容器进入运行状态。 -
docker rm
删除容器,容器转入删除状态。 -
容器异常终止
-
killed by out-of-memory
(因内存不足被终止)
宿主机内存被耗尽,也被称为 OOM(Out Of Memory)。
解决方案:非计划终止时,需要杀死最吃内存的容器。 -
container process exited
(异常终止)
当容器异常终止后,会出现Should restart?
选项。
可选择以下操作:-
yes
需要重启,容器执行start
命令,转为运行状态。 -
no
不需要重启,容器转为停止状态。
-
-
容器OOM
OOM 即 Out of Memory(内存不足),即计算机或系统在运行时,尝试分配更多内存给进程,但系统的物理内存或虚拟内存已经用尽,无法再分配给该进程或其他进程,从而导致该进程被操作系统终止或挂起。
- 如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。
- 比如在容器中部署了一个 web 服务。假设主机分配给该容器的内存上限为 1G,当脚本申请的内存大于 1G 时,容器就会触发 OOM 事件。而在这种情况下,此容器将会被强制关闭。
- 需要注意的是,关闭容器的并非是 Docker Daemon,而是宿主机操作系统。因为容器本质是一组运行在宿主机操作系统中的进程,宿主机操作系统通过 cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核 OOM 事件。
- 如果用户不想关闭该容器,可以通关
--oom-kill-disable
来禁用OOM-Killer
。- 使用此参数时,仍需注意,如果使用
-m
设置了此容器内存上限,当容器达到内存资源上限时,主机不会关闭容器,也不会继续向此容器继续分配资源,此时容器将处于 挂起(hung) 状态。
- 使用此参数时,仍需注意,如果使用
- 如果用户使用了
--oom-kill-disable
,但未使用-m
来设定上限,此时容器将尽可能多的使用主机内存资源。(主机内存有多大,它就将用多大)
容器异常退出
容器异常退出
每个 Docker 容器内部都运行一个 Init 进程,容器内的其他进程都是由 Init 进程派生出来的子进程。容器的生命周期实际上与 Init 进程的运行状态密切相关。如果一个子进程发生异常退出,它的父进程也会随之退出,最终导致 Init 进程退出,从而使整个容器停止运行。
当 Init 进程退出时,容器会自动停止。此时,Docker 无法判断进程退出是正常还是异常。当容器停止时,Docker Daemon 会尝试将容器从“已停止”状态恢复到“运行中”状态。但只有在容器启用了 --restart
参数时,Docker Daemon 才会尝试重启容器,否则容器将保持在停止状态。
容器暂停
当 Docker 暂停容器时,容器的 CPU 资源会被“剥夺”,但其他资源,如内存 (Memory) 和网络 (Network) 资源,仍然保持不变。失去 CPU 资源的进程将不会被主机的内核调度,从而使该容器处于“冻结”状态。
四、容器命令
命令清单
下面是 Docker
容器的相关命令:
命令 | 别名 | 功能 | 备注 |
---|---|---|---|
docker create | docker container create | 创建容器 | |
docker run | docker container run | 运行容器 | 必须掌握 |
docker attach | docker container attach | 连接到正在运行中的容器 | |
docker commit | docker container commit | 将镜像提交为容器 | 必须掌握 |
docker cp | docker container cp | 在容器和宿主机之间拷贝 | 必须掌握 |
docker diff | docker container diff | 检查容器里文件结构的更改 | |
docker exec | docker container exec | 在运行的容器中执行命令 | 必须掌握 |
docker export | docker container export | 将容器导出为 tar | |
docker inspect | docker container inspect | 查看容器详细信息 | 必须掌握 |
docker kill | docker container kill | 杀死容器 | 必须掌握 |
docker logs | docker container logs | 查看日志 | 必须掌握 |
docker ps | docker container ls , docker container list , docker container ps | 查看正在运行的进程 | 必须掌握 |
docker pause | docker container pause | 暂停进程 | |
docker port | docker container port | 查看容器的端口映射 | |
docker container prune | 删除停止的容器 | ||
docker rename | docker container rename | 重命名容器 | |
docker restart | docker container restart | 重启容器 | 必须掌握 |
docker rm | docker container rm , docker container remove | 删除容器 | 必须掌握 |
docker start | docker container start | 启动容器 | 必须掌握 |
docker stats | docker container stats | 查看资源占用信息 | 必须掌握 |
docker stop | docker container stop | 停止容器 | 必须掌握 |
docker top | docker container top | 查看某个容器的资源占用 | 必须掌握 |
docker unpause | docker container unpause | 继续运行容器 | |
docker update | docker container update | 更新容器配置 | |
docker wait | docker container wait | 阻止一个或多个容器停止 |
详细介绍
-
docker create
- 功能: 创建一个新的容器但不启动它
- 语法:
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
- 别名:
docker container create
- 关键参数:
-i
: 以交互模式运行容器,通常与-t
同时使用-P
: 随机端口映射-p
: 指定端口映射,格式:主机端口:容器端口
-t
: 为容器重新分配一个伪输入终端,通常与-i
同时使用--name="nginx-lb"
: 为容器指定名称-h "mars"
: 指定容器的 hostname-e username="ritchie"
: 设置环境变量--cpuset-cpus="0-2"
: 绑定容器到指定 CPU 运行-m
: 设置容器使用的最大内存--network="bridge"
: 指定容器的网络连接类型--link=[]
: 添加链接到另一个容器--volume , -v
: 绑定一个卷--rm
: 容器退出时自动删除--restart
: 自动重启容器
- 样例:
docker create --name mynginx nginx:latest
-
docker run
- 功能: 创建一个新的容器并运行一个命令
- 语法:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
- 别名:
docker container run
- 关键参数:
-d
: 后台运行容器,并返回容器 ID-i
: 以交互模式运行容器,通常与-t
同时使用-P
: 随机端口映射-p
: 指定端口映射,格式:主机端口:容器端口
-t
: 为容器重新分配一个伪输入终端,通常与-i
同时使用--name="nginx-lb"
: 为容器指定名称-h "mars"
: 指定容器的 hostname-e username="ritchie"
: 设置环境变量--cpuset-cpus="0-2"
: 绑定容器到指定 CPU 运行-m
: 设置容器使用的最大内存--network="bridge"
: 指定容器的网络连接类型--link=[]
: 添加链接到另一个容器--volume , -v
: 绑定一个卷--rm
: 容器退出时自动删除--restart
: 自动重启容器
- 样例:
docker run --name mynginx -d nginx:latest docker run -p 80:80 -v /data:/data -d nginx:latest
-
docker ps
- 功能: 列出容器
- 语法:
docker ps [OPTIONS]
- 别名:
docker container ls
,docker container list
,docker container ps
- 关键参数:
-a
: 显示所有容器,包括未运行的-f
: 根据条件过滤显示--format
: 指定返回值的模板文件,如json
或table
-l
: 显示最新的容器-n
: 列出最近创建的 N 个容器--no-trunc
: 不截断输出-q
: 静默模式,只显示容器编号-s
: 显示容器总的文件大小
- 样例:
docker ps -a
-
docker logs
- 功能: 查看容器日志
- 语法:
docker logs [OPTIONS] CONTAINER
- 别名:
docker container logs
- 关键参数:
-f ,--follow
: 跟踪日志输出--since
: 显示某个开始时间的所有日志-t, --timestamps
: 显示时间戳-n, --tail
: 仅列出最新 N 条容器日志
- 样例:
docker logs -f mynginx docker logs --since="2016-07-01" --tail=10 mynginx
-
docker attach
- 功能: 连接到正在运行中的容器
- 语法:
docker attach [OPTIONS] CONTAINER
- 别名:
docker container attach
- 关键参数:
--sig-proxy
: 是否将所有信号代理,默认是true
- 样例:
docker attach mynginx docker attach --sig-proxy=false mynginx
-
docker exec
- 功能: 在容器中执行命令
- 语法:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
- 别名:
docker container exec
- 关键参数:
-d
: 分离模式,在后台运行-i
: 即使没有附加也保持 STDIN 打开-t
: 分配一个伪终端-e
: 设置环境变量-u, --user
: 指定用户<name|uid>[:<group|gid>]
-w, --workdir
: 指定工作目录
- 样例:
docker exec -it mynginx echo "Hello bit" docker exec -it mynginx bash
-
docker start
- 功能: 启动停止的容器
- 语法:
docker start [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container start
- 样例:
docker start mynginx
-
docker stop
- 功能: 停止运行中的容器
- 语法:
docker stop [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container stop
- 关键参数:
-s
: 发送的信号
- 样例:
docker stop mynginx
-
docker restart
- 功能: 重启容器
- 语法:
docker restart [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container restart
- 关键参数:
-s
: 发送信号
- 样例:
docker restart mynginx
-
docker kill
- 功能: 强制退出容器
- 语法:
docker kill [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container kill
- 关键参数:
-s
: 发送的信号
- 注意事项:
docker kill
发送的是SIGKILL
信号,而docker stop
发送的是SIGTERM
信号 - 样例:
docker kill mynginx
-
docker top
- 功能: 查看容器中运行的进程信息,支持
ps
命令参数 - 语法:
docker top CONTAINER [ps OPTIONS]
- 别名:
docker container top
- 样例:
docker top mynginx
- 功能: 查看容器中运行的进程信息,支持
-
docker stats
- 功能: 显示容器资源的使用情况,包括 CPU、内存、网络 I/O 等
- 语法:
docker stats [OPTIONS] [CONTAINER...]
- 别名:
docker container stats
- 关键参数:
--no-stream
: 不刷新
- 样例:
docker stats --no-stream docker stats mynginx
-
docker container inspect
- 功能: 查看容器详细信息
- 语法:
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
- 关键参数:
-f
: 指定返回值的模板文件,如table
、json
-s
: 显示总的文件大小
- 注意事项:
docker inspect
会自动检查是镜像还是容器,然后显示详细信息
- 样例:
docker container inspect mynginx
-
docker port
- 功能: 用于列出指定容器的端口映射,或者查找将
PRIVATE_PORT
NAT 到面向公众的端口 - 语法:
docker port CONTAINER [PRIVATE_PORT[/PROTO]]
- 别名:
docker container port
- 样例:
docker port mynginx
- 功能: 用于列出指定容器的端口映射,或者查找将
-
docker cp
- 功能: 在容器和宿主机之间拷贝文件
- 语法:
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
- 别名:
docker container cp
- 样例:
# 将主机 /www/ 目录拷贝到容器 mynginx 的 /www 目录下 docker cp /www/ mynginx:/www/ # 将容器 /www/ 目录拷贝到主机的 /wwwbak 目录下 docker cp mynginx:/www/ /wwwbak/
-
docker diff
- 功能: 检查容器里文件结构的更改
- 语法:
docker diff CONTAINER
- 样例:
docker diff mynginx
-
docker commit
- 功能: 从容器创建一个新的镜像
- 语法:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
- 参数:
-a
: 提交的镜像作者-c
: 使用 Dockerfile 指令来创建镜像,可以修改启动指令-m
: 提交时的说明文字-p
: 在 commit 时,将容器暂停
- 样例:
docker commit c3f279d17e0a maxhou/mynginx:v01
-
docker pause
- 功能: 暂停容器中所有的进程
- 语法:
docker pause CONTAINER [CONTAINER...]
- 别名:
docker container pause
- 样例:
docker pause mynginx
-
docker unpause
- 功能: 恢复容器中所有的进程
- 语法:
docker unpause CONTAINER [CONTAINER...]
- 别名:
docker container unpause
- 样例:
docker unpause mynginx
-
docker rm
- 功能: 删除停止的容器
- 语法:
docker rm [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container rm
- 关键参数:
-f
: 通过SIGKILL
信号强制删除一个运行中的容器
- 样例:
# 删除 mynginx 容器 docker stop mynginx docker rm mynginx # 删除所有停止的容器 docker rm $(docker ps -a -q)
-
docker export
- 功能: 导出容器内容为 tar 文件
- 语法:
docker export [OPTIONS] CONTAINER
- 别名:
docker container export
- 关键参数:
-o
: 写入到文件
- 样例:
# 导出 nginx 为 tar 文件 docker export -o mynginx202203.tar mynginx
-
docker wait
- 功能: 阻塞运行直到容器停止,然后打印出它的退出代码
- 语法:
docker wait CONTAINER [CONTAINER...]
- 别名:
docker container wait
- 样例:
docker wait mynginx
-
docker rename
- 功能: 重命名容器
- 语法:
docker rename CONTAINER NEW_NAME
- 别名:
docker container rename
- 样例:
docker rename mynginx myweb
-
docker container prune
- 功能: 删除所有停止的容器
- 语法:
docker container prune [OPTIONS]
- 关键参数:
-f
,--force
: 不提示是否进行确认
- 样例:
docker container prune
-
docker update
- 功能: 更新容器配置
- 语法:
docker update [OPTIONS] CONTAINER [CONTAINER...]
- 别名:
docker container update
- 关键参数:
--cpus
: 设置 CPU 数量--cpuset-cpus
: 使用哪些 CPU--memory
: 设置内存限制--memory-swap
: 设置交换内存--cpu-period
: 用来指定容器对 CPU 的使用要在多长时间内做一次重新分配--cpu-quota
: 用来指定在这个周期内,最多可以有多少时间用来跑这个容器
- 样例:
# 更新内存 docker update -m 400m myweb
五、容器操作案例
容器的状态迁移
下面演示一下容器的基本的状态改变操作:
- 通过
docker create
命令进行容器的创建:
ubuntu@VM-8-2-ubuntu:~$ docker create --name mynginx -p 8080:80 nginx:1.24.0
4c269e3619d4b40a22d94ef031edab6abaf06059020d3e520f92b0d62bff55ee
- 通过
docker ps
命令可以查看创建的容器:
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
23400afbdb50 nginx:1.24.0 "/docker-entrypoint.…" About a minute ago Created mynginx
- 随后启动容器:
ubuntu@VM-8-2-ubuntu:~$ docker start mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mynginx
- 通过
docker stop
停止容器:
ubuntu@VM-8-2-ubuntu:~$ docker stop mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 2 minutes ago Exited (0) 3 seconds ago mynginx
- 再次启动容器后 kill 容器:
ubuntu@VM-8-2-ubuntu:~$ docker start mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker kill mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 4 minutes ago Exited (137) 3 seconds ago mynginx
- 启动容器后暂停容器:
ubuntu@VM-8-2-ubuntu:~$ docker start mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker pause mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 4 minutes ago Up 7 seconds (Paused) 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mynginx
- 恢复容器:
ubuntu@VM-8-2-ubuntu:~$ docker unpause mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 5 minutes ago Up 38 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mynginx
- 重启容器,可以观察到启动时间变快了:
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 9 minutes ago Up 5 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mynginx
ubuntu@VM-8-2-ubuntu:~$ docker restart mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker ps -a | grep mynginx
4c269e3619d4 nginx:1.24.0 "/docker-entrypoint.…" 10 minutes ago Up 2 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mynginx
- 通过
docker rm
可以删除容器:
ubuntu@VM-8-2-ubuntu:~$ docker stop mynginx
mynginx
ubuntu@VM-8-2-ubuntu:~$ docker rm mynginx
mynginx
容器批量操作
命令 | 解释 |
---|---|
docker container ls -qf name=xxx | 根据容器名称过滤,返回与名称匹配的容器 ID。 |
docker container ls -f status=running | 根据容器状态过滤,显示所有正在运行的容器。 |
docker container ls -aq | 静默模式,列出所有容器的容器 ID(包括运行中和停止的容器)。 |
docker container ls -f ancestor=xxx | 根据镜像名称过滤,显示所有使用指定镜像(如 xxx )的容器。 |
docker container ls -f ancestor=xxx | 根据镜像 ID 过滤,显示所有使用指定镜像 ID(如 xxx )的容器。 |
参数:
-q
:只返回容器的 ID,不显示其他信息。-a
:包括所有容器(包括停止的容器)。-f
/--filter
:允许根据不同的条件进行过滤,条件如状态、镜像等。
我们可以利用上面的批量选择,执行一些对容器的批量操作,比如想要批量删除容器:
# 根据容器状态进行删除
docker container rm $(docker container ls -q --filter status=exited)
# 删除所有容器
docker container rm $(docker container ls -aq)
类比这种方式,我们可以对容器进行各种批量操作,下面是相关的删除操作:
操作描述 | 命令 |
---|---|
根据容器状态删除已退出容器 | docker container rm $(docker container ls -q --filter status=exited) |
删除所有容器(包括运行中的和已停止的) | docker container rm $(docker container ls -aq) |
删除所有已停止的容器 | docker container rm $(docker container ls -aq --filter "status=exited") |
删除所有悬挂的容器(未运行的容器) | docker container prune -f |
停止并删除所有容器 | docker stop $(docker ps -q) && docker rm $(docker ps -aq) |
删除指定名称的容器 | docker container rm <container_name> <container_name> |
容器交互模式
attached 模式
对于下面的命令:
# 通过 nginx 镜像创建一个容器, 映射 80 端口
[wqy@vm~]$ docker container run -p 80:80 nginx
-p 80:80
表示端口映射,第一个端口表示映射到宿主机的端口,第二个端口表示映射到 Docker 容器的端口。- 通过这种方式运行的容器,就是attached模式,容器在前台运行。
- 访问服务器网址的时候,每访问一次,命令窗口就会打印一次日志,Docker 容器日志会实时展现到窗口并占用此端口
attached
模式仅适用于容器和程序的调试阶段- 而在linux服务器下,通过Ctrl+C信号就可以停止docker服务,实在不太方便(稳定),为了更加稳定,一般可以选用
detached
模式(后文介绍)
detached 模式
在 docker container run -p 80:80 nginx
命令基础上加 -d
/ --detach
选项表示 detached 模式
docker container run -p -d 80:80 nginx
对于 detached
模式:
- 在后台运行,启动后只显示容器 ID,并且可以输入任何命令
- 关掉窗口后依然继续运行,停止和删除容器都需要使用 shell 命令,减少误操作的可能
- 一般更建议使用该模式
- 我们可以通过
docker container attach <name>
将detached模式下的容器转为attached
interactive 模式
当我们创建好一个容器之后, 可能需要去容器内部获取信息或执行命令,就需要进入到交互式模式。
例如创建一个 Ubuntu 容器后,需要到系统里输入各种 Shell 命令和系统进行交互,就需要先进入交互式模式。
docker container run -it nginx sh
上面的命令用于启动一个 nginx 容器,并在其中运行 sh(shell)命令,进入容器的交互式终端(Shell)。
我们可以在Shell中执行下面的命令:
bin boot dev docker-entrypoint.d docker-entrypoint.sh
etc home lib lib64 media mnt opt proc root run
sbin srv sys tmp usr var
-i:保持容器运行。通常与 -t 同时使用,加入 it 这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭
-t
:为容器重新分配一个伪输入终端,通常与 -i 同时使用
针对一个已经运行的容器里进入到交互模式
对于一个已经运行的容器,我们可以通过下面的命令,将其转为交互式模式:
docker container exec -it <name> sh
同时可以通过 exit
退出交互式模式。
容器 与 宿主机 文件拷贝
一般我们可以通过 以下方法 实现 容器 与 宿主机间的文件拷贝:
docker cp
命令- Docker 网络
- 挂载卷(Volume)
- 使用共享文件夹
下面分别进行简单举例:
1, 使用 docker cp
命令
docker cp
命令可以在宿主机与容器之间直接拷贝文件或目录。
- 从宿主机拷贝文件到容器
docker cp /path/on/host <container_id>:/path/in/container# 示例
docker cp /home/user/data.txt my_container:/root/data.txt
# 将宿主机上的 `/home/user/data.txt` 文件拷贝到容器 `my_container` 的 `/root/data.txt` 路径。
-
/path/on/host
:宿主机上的文件或目录路径。 -
<container_id>
:容器的 ID 或名称。 -
/path/in/container
:容器内目标路径。 -
从容器拷贝文件到宿主机
docker cp <container_id>:/path/in/container /path/on/host‘# 示例
docker cp my_container:/root/data.txt /home/user/data.txt
# 将容器 my_container 中 /root/data.txt 文件拷贝到宿主机的 /home/user/data.txt 路径。
<container_id>
:容器的 ID 或名称。/path/in/container
:容器内的文件或目录路径。/path/on/host
:宿主机上的目标路径。
- 使用挂载卷(Volume)
卷是 Docker 提供的一种持久化数据的方法。通过挂载卷,可以让容器与宿主机共享文件和目录。
使用命令行创建卷并挂载
我们可以在启动容器时通过 -v
或 --mount
选项挂载一个宿主机目录到容器的某个路径,这样容器和宿主机就可以共享该目录的文件。
docker run -v /path/on/host:/path/in/container <image_name>
/path/on/host
:宿主机上的目录。/path/in/container
:容器内的目录路径。
- 使用共享目录(Bind Mount)
与卷类似**,绑定挂载(Bind Mount)允许容器直接访问宿主机上的指定目录。通过绑定宿主机和容器的文件路径,可以让文件互通。**
docker run --mount type=bind,source=/path/on/host,target=/path/in/container <image_name>
source=/path/on/host
:宿主机目录路径。target=/path/in/container
:容器内目录路径。
- 使用 Docker 网络(适用于容器间通信)
如果容器之间需要共享文件,可以通过 Docker 网络让容器直接访问宿主机或其他容器的服务。在这种场景下,文件传输可能通过网络协议(如 FTP、HTTP、NFS)进行。
例如:
- 通过 NFS 或 Samba 等协议共享文件。
- 在宿主机上运行 FTP 服务,然后在容器内访问宿主机的 FTP 服务。
容器 自动删除 与 自动重启
- 容器的自动删除
容器自动删除是指当容器停止运行时,Docker 会自动删除容器以释放资源。这个功能通常用于短期任务或一次性任务的容器,以避免残留停止的容器。
我们可以在启动容器时 通过 -rm 参数设置容器的自动删除
docker run --rm ubuntu
- 容器自动重启
docker run --restart always <image_name>
这个指令保证容器在任何情况下停止后都能自动重启。
容器环境变量设置
在 Docker 中,环境变量可以在容器运行时传递给容器内部的应用或服务,下面会介绍一些设置环境变量的方法:
1. 使用 -e
或 --env
选项设置环境变量
当你使用 docker run
命令启动容器时,可以使用 -e
或 --env
选项来设置环境变量。每个 -e
或 --env
选项后跟一个 KEY=VALUE
对。
示例:
docker run --rm -e MY_VAR=value ubuntu printenv MY_VAR
-e MY_VAR=value
:设置容器内的环境变量MY_VAR
的值为value
。printenv MY_VAR
:容器内执行printenv MY_VAR
命令,输出环境变量MY_VAR
的值。
这个命令执行后会输出value
2. 使用 --env-file
选项从文件加载环境变量
如果有多个环境变量需要设置,可以将它们存储在一个文件中,并使用 --env-file
选项来加载这些环境变量。
- 环境变量文件示例(
.env
文件):
MY_VAR=value
ANOTHER_VAR=another_value
- 命令:
docker run --rm --env-file .env ubuntu printenv MY_VAR
--env-file .env
:从.env
文件加载环境变量并传递给容器。printenv MY_VAR
:容器内执行printenv MY_VAR
,输出MY_VAR
的值。
3. 使用 docker exec
修改正在运行容器的环境变量
如果容器已经在运行,并且你想修改它的环境变量,可以通过 docker exec
命令进入容器并在容器内修改环境变量。
示例:
docker exec -it <container_id> bash
进入容器后,可以使用 export
命令来设置环境变量:
export MY_VAR=value
此时,MY_VAR
的值会被修改为 value
,但是这种修改只会在当前的 shell 会话中有效。如果你退出容器,环境变量会丢失。
4. 使用 --env
设置多个环境变量
我们也可以在同一 docker run
命令中设置多个环境变量。
- 示例:
docker run --rm -e VAR1=value1 -e VAR2=value2 ubuntu bash -c 'echo $VAR1 $VAR2'
- 这会同时设置
VAR1
和VAR2
两个环境变量,并输出它们的值。
查看容器的详细信息
- 查看容器的基本信息:
docker ps
和docker inspect
a. docker ps
:查看正在运行的容器(-a 查看所有容器)
docker ps
命令用于列出当前正在运行的容器,并显示其基本信息,比如容器 ID、名称、镜像、状态、端口映射等。
docker ps
输出示例:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8f9b711b8fa ubuntu "bash" 2 minutes ago Up 2 minutes my_container
b. docker inspect
:查看容器的详细信息
docker inspect
命令提供容器的详细信息,包括其配置、网络设置、挂载卷等。你可以通过容器 ID 或容器名称来指定需要查看的容器。
docker inspect <container_id_or_name>
输出示例:
[{"Id": "d8f9b711b8fa...","Created": "2024-12-28T08:24:35.275285626Z","Path": "bash","Args": [],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 1234,"ExitCode": 0,"Error": "","StartedAt": "2024-12-28T08:24:37.607128397Z","FinishedAt": "2024-12-28T08:24:37.607128397Z"},"Image": "sha256:...","ResolvConfPath": "/var/lib/docker/containers/d8f9b711b8fa/resolv.conf","Mounts": [],"Config": {"Hostname": "d8f9b711b8fa","Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"NetworkSettings": {"Networks": {"bridge": {"IPAddress": "172.17.0.2","MacAddress": "02:42:ac:11:00:02"}}}}
]
这个 JSON 格式的输出包含了容器的所有信息,比如:
- Id:容器 ID
- Created:容器创建时间
- State:容器的状态(是否运行、退出代码等)
- Config:容器的配置(如环境变量、命令等)
- NetworkSettings:容器的网络配置(IP 地址、网络类型等)
- Mounts:挂载的卷和文件系统
- 查看容器的资源使用情况:
docker stats
docker stats
命令可以查看容器的实时资源使用情况,如 CPU、内存、网络 I/O 等。
docker stats
输出示例:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
d8f9b711b8fa my_container 0.02% 10.5MiB / 1.95GiB 0.53% 1.2kB / 0B 1.5MB / 0B 2
我们也可以指定查看某个容器的资源使用情况:
docker stats <container_id_or_name>
- 查看容器的日志:
docker logs
通过 docker logs
命令,你可以查看容器的标准输出和标准错误输出日志。
加上 -f
参数 可以查看容器日志的实时输出。
docker logs <container_id_or_name>
- 查看容器的网络信息:
docker network inspect
如果想查看容器的网络配置,可以使用 docker network inspect
命令。首先可以使用 docker network ls
查看当前可用的网络。
docker network ls
然后,通过 docker network inspect
来查看某个网络的详细信息,其中也包括与该网络连接的容器信息。
docker network inspect <network_name_or_id>
- 查看容器的环境变量:
docker exec
和printenv
你可以通过 docker exec
进入容器并使用 printenv
命令查看容器内的所有环境变量:
docker exec -it <container_id_or_name> printenv
如果你只关心某个特定的环境变量,可以通过 grep
过滤:
docker exec -it <container_id_or_name> printenv | grep MY_VAR
- 查看容器内的进程:
docker top
docker top
命令可以显示容器内的进程信息,类似于 Linux 上的 top
命令。
docker top <container_id_or_name>
它会显示容器内部正在运行的进程列表,包括 PID、进程名、内存使用情况等。
- 查看容器的文件系统:
docker diff
docker diff
命令可以列出容器文件系统中的变化,显示自容器启动以来做出的文件修改(增加、删除、修改)。
docker diff <container_id_or_name>
- 查看容器的挂载卷:
docker inspect
容器的挂载卷信息也可以通过 docker inspect
获取,具体是在输出的 Mounts
部分。
docker inspect <container_id_or_name> | grep Mounts -A 10
容器镜像的导入导出
下面分别列出容器与镜像的导入导出命令:
操作 | 命令格式 | 示例 | 解释 |
---|---|---|---|
导出容器 | docker export <container_id> > <filename>.tar | docker export my_container > backup.tar | 将容器的文件系统导出为 .tar 格式的文件,不包括镜像和容器的元数据。 |
导入容器 | docker import <filename>.tar <image_name>:<tag> | docker import backup.tar my_image:latest | 从 .tar 文件中导入容器的文件系统并创建一个新的镜像。 |
导出镜像 | docker save -o <filename>.tar <image_name>:<tag> | docker save -o my_image.tar my_image:latest | 将 Docker 镜像导出为 .tar 文件,可以在其他主机上通过 docker load 导入使用。 |
导入镜像 | docker load -i <filename>.tar | docker load -i my_image.tar | 从 .tar 文件中加载镜像,并将其添加到本地 Docker 镜像列表中。 |
镜像的资源查看
这里直接列举相关的docker 资源查看命令:
命令 | 说明 |
---|---|
docker images 或 docker image ls | 列出所有本地镜像及其信息 (名称、标签、大小等) |
docker inspect <image_name> | 查看镜像的详细元数据 |
docker history <image_name> | 查看镜像的历史层信息及构建过程 |
docker system df | 查看 Docker 系统的磁盘使用情况(镜像、容器、卷) |
docker image inspect <image_name> | 查看镜像的详细层次结构信息 |
镜像的日志查看
下面的表格介绍了 使用 docker logs 查看日志的方式:
操作 | 命令格式 | 示例 | 说明 |
---|---|---|---|
查看容器日志 | docker logs <container_id_or_name> | docker logs my_container | 显示指定容器的标准输出和标准错误输出。 |
实时查看容器日志 | docker logs -f <container_id_or_name> | docker logs -f my_container | 实时查看容器日志,类似 tail -f ,会持续显示新产生的日志条目。 |
查看容器日志的特定时间范围(自某时间点起) | docker logs --since "<time>" <container_id_or_name> | docker logs --since "2024-12-01T00:00:00" my_container | 查看自某个时间点以来的日志。时间可以是相对时间(如 10m 表示过去 10 分钟)。 |
查看容器日志的特定时间范围(直到某时间点) | docker logs --until "<time>" <container_id_or_name> | docker logs --until "2024-12-01T00:00:00" my_container | 查看直到某个时间点的日志。 |
查看容器日志的最新部分 | docker logs --tail <number> <container_id_or_name> | docker logs --tail 100 my_container | 查看容器日志的最后 N 行,帮助你快速查看最新的日志条目。 |
查看容器日志并显示时间戳 | docker logs -t <container_id_or_name> | docker logs -t my_container | 在每条日志前添加时间戳,帮助你了解日志产生的时间。 |
实时查看日志并显示时间戳 | docker logs -ft <container_id_or_name> | docker logs -ft my_container | 实时查看容器日志,并且每条日志会带有时间戳。 |
查看容器日志并实时跟踪最新部分 | docker logs -f --tail <number> <container_id_or_name> | docker logs -f --tail 50 my_container | 查看容器的最后 N 行日志,并且实时跟踪新的日志更新。 |
参数部分:
-f
:实时查看日志输出,类似于 Linux 命令tail -f
。--since
和--until
:用于指定时间范围,--since
是自某个时间点以来,--until
是直到某个时间点。--tail
:仅查看日志的最后 N 行。-t
:在日志行前加上时间戳,便于查看日志发生的时间。
容器的资源查看
下面简单介绍一些命令:监控和查看容器的资源消耗,如 CPU、内存、磁盘等:
操作描述 | 命令 |
---|---|
查看所有容器的实时资源使用情况 | docker stats |
查看单个容器的实时资源使用情况 | docker stats <container_name_or_id> |
查看容器的详细信息(包括资源限制等) | docker inspect <container_name_or_id> |
查看容器的内存限制 | docker inspect --format '{{.HostConfig.Memory}}' <container_name_or_id> |
查看容器的 CPU 配额 | docker inspect --format '{{.HostConfig.CpuShares}}' <container_name_or_id> |
查看容器的日志 | docker logs <container_name_or_id> |
查看容器的文件系统使用情况 | docker system df |
六、综合实战
Mysql 容器化安装
1进入docker hub 官网,查找 mysql 的镜像,可以看到很多版本,这里选择一个使用人数相对较多的:
图片图片图片
通过 docker pull
拉取镜像
ubuntu@VM-8-2-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
MySQL 的默认端口是 3306,且有密码。根据官网的启动用例:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
解释一下部分字段:
-
--name some-mysql
:为新启动的容器指定一个名字,这里容器的名字是some-mysql
。 -
-e MYSQL_ROOT_PASSWORD=my-secret-pw
:使用-e
参数设置环境变量。这个环境变量MYSQL_ROOT_PASSWORD
用来设置 MySQL 数据库的 root 用户密码。这里密码设置为my-secret-pw
。 -
-d
:指示 Docker 在后台运行容器,并返回容器 ID。容器不会绑定到终端。
执行下面的命令:
ubuntu@VM-8-2-ubuntu:~$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 8200:3306 -d mysql:5.7
4a542dd7bfe0a8be6d47fb2cbd6d9f165596d56b07463eb8d6a702a92c577d00
此时进入容器,可以发现mysql可以正常登录:
ubuntu@VM-8-2-ubuntu:~$ docker exec -it mysql bash
bash-4.2# mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)Copyright (c) 2000, 2023, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
通过下面的代码释放空间:
docker stop mysql
docker rm mysql
Redis 容器化安装
Redis 出现的原因
在 Web 应用发展的初期,关系型数据库受到了广泛的关注和应用。这是因为当时的 Web 站点访问量和并发不高,交互也较少。随着访问量的提升,使用关系型数据库的 Web 站点逐渐开始在性能上遇到瓶颈,而瓶颈的主要原因通常是在磁盘的 I/O 上。随着互联网技术的进一步发展,各类应用层层叠加,导致如今在云计算、大数据盛行的时代,对性能有了更高的要求,主要体现在以下几个方面:
- 低延迟的读写速度:快速响应的应用能显著提升用户的满意度。
- 支撑海量数据和流量:例如,搜索引擎等大型应用需要处理 PB 级别的数据,并能应对百万级的并发流量。
为了解决这些问题,NoSQL 数据库应运而生,它具备高性能、可扩展性强和高可用等优点,广泛受到开发人员和系统管理员的青睐。
Redis 是什么
Redis(全称:Remote Dictionary Server,中文名为远程字典服务器)是目前最受欢迎的 NoSQL 数据库之一。它使用 ANSI C 编写,是一个开源、基于内存、支持多种数据结构的键值对存储数据库,具备如下特性:
- 基于内存运行,性能高效:由于数据存储在内存中,读写速度非常快。
- 支持分布式,具备理论上的无限扩展性:可以横向扩展,支持大规模分布式系统。
- 键值存储系统:数据以键值对形式存储,简单而高效。
- 开源且使用 ANSI C 编写:遵循 BSD 协议,并支持多种编程语言的 API。
- 支持持久化:可以将数据持久化到磁盘,也可以仅作为内存存储使用。
Redis 的应用场景
几乎所有的大型互联网公司都在使用 Redis。Redis 提供了多种数据类型,如 String 类型、哈希类型、列表类型、集合类型、顺序集合类型,这些数据结构能够支持多种应用场景。以下是 Redis 常见的应用场景:
- 缓存系统:尤其适用于“热点”数据(即频繁读取、少量写入的数据),能大幅提高系统响应速度。
- 计数器:适用于需要实时计数的场景,如访问量统计、投票系统等。
- 消息队列系统:通过 Redis 的 List 和 Pub/Sub 功能,构建高效的消息队列。
- 实时排行榜:Redis 的有序集合(Sorted Set)能高效地支持实时排行榜的需求。
- 社交网络:如用户关注、评论、点赞等社交互动操作,可以通过 Redis 高效处理。
Redis 的高性能和灵活性使其成为许多 Web 应用中不可或缺的组件,尤其是在需要快速响应和处理海量数据时,Redis 的优势尤为明显。
C++ 容器制作
-
首先通过
docker pull ubuntu:22.04
拉取镜像 -
启动容器:
ubuntu@VM-8-2-ubuntu:~$ docker run --name mygcc -it ubuntu:22.04 bash
- 更新apt包并安装gcc/vim:
apt update
apt install gcc vim -y
- 编辑代码:
root@8f8244b7f41d:/# mkdir src
root@8f8244b7f41d:/# cd src
root@8f8244b7f41d:/src# vim demo.c
- 执行代码:
root@8f8244b7f41d:/src# gcc demo.c -o demo
root@8f8244b7f41d:/src# ./demo
hello docker
- 此时退出容器
root@8f8244b7f41d:/src# exit
exit
ubuntu@VM-8-2-ubuntu:~$
可以看出容器已经退出,如果想再次运行通过restart恢复即可。
容器资源更新
- 首先运行一个 nginx 容器
ubuntu@VM-8-2-ubuntu:~$ docker run -d --name mynginx1 -p 8080:80 nginx:1.24.0
88c1f95c0066a3658ccee40a9207b5f44ff970a4e815ad8b05297b5875316f6f
- 通过 docker top 查看容器中的进程, 添加 aux 查看内存和CPU信息
ubuntu@VM-8-2-ubuntu:~$ docker top mynginx1 aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2378550 0.1 0.3 8932 5760 ? Ss 20:00 0:00 nginx: master process nginx -g daemon off;
message+ 2378598 0.0 0.1 9320 2772 ? S 20:00 0:00 nginx: worker process
message+ 2378599 0.0 0.1 9320 2772 ? S 20:00 0:00 nginx: worker process
- 通过 docker stat 查看资源的动态变化:
ubuntu@VM-8-2-ubuntu:~$ docker top mynginx1 aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2378550 0.1 0.3 8932 5760 ? Ss 20:00 0:00 nginx: master process nginx -g daemon off;
message+ 2378598 0.0 0.1 9320 2772 ? S 20:00 0:00 nginx: worker process
message+ 2378599 0.0 0.1 9320 2772 ? S 20:00 0:00 nginx: worker process
- 通过 docker update 更新容器的最大内存
ubuntu@VM-8-2-ubuntu:~$ docker update -m 300m --memory-swap 600m mynginx1
mynginx1
- 再次执行 docker stat 查询容器状态,可以看到最大内存被限制为 300mb
ubuntu@VM-8-2-ubuntu:~$ docker update -m 300m --memory-swap 600m mynginx1
mynginx1
- 停止容器并释放资源:
docker stop <id>
docker rm <id>