目录
[3.1.docker container ls](#3.1.docker container ls)
[3.1.1. 基础参数:-a 和 -q](#3.1.1. 基础参数:-a 和 -q)
[3.1.2. 过滤参数:-f 或 --filter](#3.1.2. 过滤参数:-f 或 --filter)
[3.1.3.命令替换------(command)](#3.1.3.命令替换——(command))
[4.2.detached 模式(后台模式)](#4.2.detached 模式(后台模式))
我们在上一篇文章里面讲了很多的docker容器的命令,那么光讲那么多命令却不拿来用其实是不好的,我们在这篇文章里面会着重于docker容器的实战部分,讲解大量实用案例。
一.容器的基本操作
先查看一下本地有啥镜像

我们只想要nginx的1.22.0版本的,这里却没有,我们需要先docker pull吗?完全没有必要,我们直接docker run即可
docker run -d --name mynginx001 -p 8081:80 nginx:1.22.0

我们发现这个docker run会自动去pull这个nginx的1.22.0版本的。

执行完后我们看看

cpp
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
214522b9d48f nginx:1.22.0 "/docker-entrypoint...." About a minute ago Up About a minute 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mynginx001
容器也正常运行起来了!!还行不,接下来我们去浏览器看看
bash
http://150.158.139.86:8081/

我们可以获取这个容器的更多信息
bash
docker inspect mynginx001
docker inspect会自动识别mynginx001是镜像还是容器
- 如果说mynginx001是镜像,就会调用docker image inspect mynginx001
- 如果说mynginx001是容器,就会调用docker container inspect mynginx001

......

这里有很多信息,我不想多说。
其实我们也可以查看一下这个容器的日志
bash
docker logs -f -n 5 mynginx001

我们现在去浏览器刷新一下

怎么样?日志是不是变多了!!
我们接着往下面看
bash
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
214522b9d48f nginx:1.22.0 "/docker-entrypoint...." 9 minutes ago Up 9 minutes 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mynginx001
我们现在需要删掉这个容器

这样子不行,我们需要先停止,再删除

非常的完美了吧!!
二.容器的状态迁移
先看本地的镜像

接下来我们就执行下面这个命令
bash
docker create --name myginx002 -p 8002:80 nginx:1.22.0

我们查看一下它的状态

显然是没有启动,并且处于Created状态。

接下来我们就启动这个容器
bash
docker start myginx002

我们去看看它的状态
cpp
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 2 minutes ago Up 2 seconds 0.0.0.0:8002->80/tcp, [::]:8002->80/tcp myginx002
很显然,启动成功了,并且状态是Up

接下来我们执行下面这个命令
bash
docker kill myginx002

现在我们去观察一下这个容器的状态
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 5 minutes ago Exited (137) 1 second ago myginx002
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
状态变成了下面这样子

现在我们继续启动这个容器
bash
docker start myginx002

当然它的状态也变成了下面这个

接下来我们执行下面这个命令
cpp
docker stop myginx002

我们查看一下状态
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 8 minutes ago Exited (0) 3 seconds ago myginx002
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
我们看看它的状态

现在我们接着重新启动我们的容器
bash
docker start myginx002

当然它的状态也变成了下面这个

接下来我们执行下面这个命令
bash
docker restart myginx002
我们看看它的前后状态变化
cpp
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 12 minutes ago Up About a minute 0.0.0.0:8002->80/tcp, [::]:8002->80/tcp myginx002
root@VM-16-14-ubuntu:~# docker restart myginx002
myginx002
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 12 minutes ago Up 2 seconds 0.0.0.0:8002->80/tcp, [::]:8002->80/tcp myginx002
状态变化还是很明显的

接下来我们先去浏览器看看

现在还是可以正常刷新的!!!
执行下面这个命令
bash
docker pause myginx002

现在我们去查看一下它的状态
cpp
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
691eb910da07 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Up 4 minutes (Paused) 0.0.0.0:8002->80/tcp, [::]:8002->80/tcp myginx002

状态变这样子了。有一个Paused!!
现在我们回去浏览器,点击刷新,发现一直就是刷新不了了,但是原来的界面还在

现在我们执行下面这个命令
bash
docker unpause myginx002

去查看一下容器的状态

我们回去浏览器,发现可以正常刷新了

三.容器的批量搜索技巧
3.1.docker container ls
这里涉及到一个新的命令------docker container ls
实际上,**docker ps 是 docker container ls 的简写形式。**在早期的 Docker 版本中,我们使用 docker ps 来列出容器。后来,Docker 引入了更明确的命令结构,将命令按功能分组,例如 container、image、network 等。因此,docker container ls 是更现代、更推荐的写法,但 docker ps 仍然被广泛支持和使用。
首先,我们要明白 docker container ls(或者它的老版本写法 docker ps)是做什么的。
- 作用:列出当前系统上的容器。
- 类比:就像在 Windows 中打开"任务管理器"查看运行的程序,或者在 Linux/Mac 中使用 ps 命令查看进程一样。docker container ls 就是用来查看 Docker 世界的"进程"(即容器)的。
现在,我们来深入理解你列出的这些"调味品"(参数),它们能让 docker container ls 这道"主菜"变得更符合你的口味。
3.1.1. 基础参数:-a 和 -q
-a:显示所有容器。
- 默认情况:docker container ls 只显示正在运行的容器。
- 加上 -a:会显示所有状态的容器,包括正在运行的和已经退出/停止的。
- 使用场景:当你需要查看曾经运行过的容器,或者确认某个容器是否已经停止时。
命令示例:
bash
# 只查看正在运行的容器
docker container ls
# 查看所有容器(包括已停止的)
docker container ls -a
-q:静默模式,只返回容器 ID。
- 默认情况:docker container ls 会返回一个表格,包含容器 ID、镜像、命令、创建时间、状态、端口等详细信息。
- 加上 -q:它只返回纯粹的容器 ID,没有其他任何信息。
- 使用场景:这是批量操作的关键! 当你需要将一堆容器的 ID 传递给另一个命令时(比如停止所有容器、删除所有容器),-q 就变得极其有用。
命令示例:
bash
# 查看所有容器的详细信息
docker container ls -a
# 只获取所有容器的 ID(注意:包括已停止的)
docker container ls -aq
3.1.2. 过滤参数:-f 或 --filter
基本语法:
bash
docker container ls --filter "<属性键>=<属性值>"
# 或者使用短格式
docker container ls -f "<属性键>=<属性值>"
- 属性键:你想根据容器的哪个特征来过滤。(例如:status、name......我们下面就会讲)
- 属性值:你希望这个特征符合什么条件。(例如:running、my-app、nginx)
工作原理:当你使用 --filter 时,Docker 会:
- 检查所有符合条件的容器。
- 只返回那些属性与你的过滤条件匹配的容器。
- 忽略所有不匹配的容器。
让我们来深入理解你列出的以及几个最常用的属性键。
1. 按状态过滤:status
这是最常用的过滤器之一。
作用:根据容器的运行状态来筛选。
常用值:
- running:正在运行
- exited:已停止/已退出
- created:已创建但未启动
- paused:已暂停
- restarting:正在重启
示例:
bash
# 只显示正在运行的容器
docker container ls -f "status=running"
# 等价于不带 -a 的 docker ps,但这样写更明确
# 显示所有已停止的容器
docker container ls -a -f "status=exited"
# 注意:查看已停止的容器通常需要加上 -a
2. 按名称过滤:name
- 作用:根据容器的名称来筛选。
- 重要特点:它使用的是模糊匹配(包含匹配),而不是精确匹配。只要容器名字包含你提供的字符串,就会被找出来。
示例:
假设你有以下几个容器:web-server, my-database, database-backup, old-web-container。
bash
# 查找名字中包含 "web" 的容器
docker container ls -a -f "name=web"
# 结果:会显示 'web-server' 和 'old-web-container'
# 查找名字中包含 "data" 的容器
docker container ls -a -f "name=data"
# 结果:会显示 'my-database' 和 'database-backup'
3. 按镜像过滤:ancestor
作用:根据容器是由哪个镜像创建的来筛选。
"祖先"的含义:一个容器是从一个镜像产生的,所以镜像就是容器的"祖先"。
它可以匹配:
- 镜像名(如 nginx, ubuntu)
- 镜像名:标签(如 nginx:latest, ubuntu:20.04)
- 镜像 ID(长的哈希值,如 d123a6c6c6c6)
示例:
bash
# 查找所有从 'nginx' 镜像(任何标签)创建的容器
docker container ls -f "ancestor=nginx"
# 查找所有从 'ubuntu:20.04' 这个特定镜像创建的容器
docker container ls -a -f "ancestor=ubuntu:20.04"
# 查找所有从某个特定镜像ID创建的容器
docker container ls -a -f "ancestor=d123a6c6c6c6"
- 按标签过滤:label
- 这是一个非常强大且在生产中常用的过滤器,用于筛选使用了自定义标签的容器。
- 作用:根据容器附带的 label 来筛选。
- 背景:在运行容器时,可以使用 --label 或 -l 参数为容器添加自定义的键值对,用于标识其角色、环境等(例如 --label env=production)。
示例:
bash
# 假设你运行容器时这样打标签:
# docker run -d --label "env=prod" --label "team=backend" ... nginx
# 查找所有带有 `env=prod` 标签的容器
docker container ls -f "label=env=prod"
# 查找所有带有 `team` 这个标签键的容器,无论其值是什么
docker container ls -f "label=team"
3.1.3.命令替换------$(command)
什么是命令替换?
我们这里讲的命令替换就是$(command)
它的作用就是:先执行括号(或反引号)中的命令,然后将这个命令的输出结果替换到当前位置。
举个例子:
假设我们有一个命令 echo "Hello",它会输出字符串 "Hello"。
如果我们这样写:
bash
echo $(echo "Hello")
那么执行步骤是:
先执行 echo "Hello",得到输出 "Hello"。
然后将 $(echo "Hello") 替换为 "Hello",所以整个命令变成了:
bash
echo "Hello"
然后执行这个命令,最后输出 "Hello"。
看起来好像多此一举,但实际上,命令替换的真正威力在于,它可以让一个命令的输出作为另一个命令的参数。
事实上,这个在在 Docker 中的实际应用其实是非常广泛的
示例一:停止所有正在运行的容器
在 Docker 中,我们经常需要处理多个容器。
比如,我们想停止所有正在运行的容器。
没有命令替换的做法:
- 先运行 docker container ls 查看正在运行的容器,记下它们的容器 ID。
- 然后运行 docker container stop <容器ID1> <容器ID2> ...,手动输入所有容器 ID。
这样做很麻烦,而且如果容器很多,很容易出错。
使用命令替换的做法:
bash
docker container stop $(docker container ls -q)
我们来分解一下这个命令:
首先,Shell 会执行 $(docker container ls -q) 中的命令 docker container ls -q。
docker container ls -q 会列出所有正在运行的容器的 ID(-q 表示只显示 ID)。
假设当前运行着三个容器,那么 docker container ls -q 的输出可能是:
bash
a1b2c3d4e5f6
x1y2z3u4v5w6
k9l8m7n6o5p4
然后,命令替换会发生,$(docker container ls -q) 会被替换为这三个 ID,整个命令变成:
bash
docker container stop a1b2c3d4e5f6 x1y2z3u4v5w6 k9l8m7n6o5p4
最后,Shell 执行这个命令,停止这三个容器。
这样,我们只需要一行命令就可以停止所有运行中的容器,而不需要手动输入每个容器的 ID。
另一个例子:删除所有已退出的容器
我们经常需要清理已经退出的容器。我们可以这样写:
bash
docker container rm $(docker container ls -aq -f status=exited)
分解:
docker container ls -aq -f status=exited:
- -a:显示所有容器(包括已退出的)
- -q:只显示容器 ID
- -f status=exited:过滤出状态为已退出的容器
假设这个命令输出两个已退出容器的 ID:
bash
c1
c2
然后命令替换会发生,整个命令变成:
bash
docker container rm c1 c2
命令替换的注意事项
当然看了上面2个例子,我们应该就能看懂下面这个了吧
bash
# 停止所有运行中的容器
docker container stop $(docker container ls -q)
# 删除所有已退出的容器
docker container rm $(docker container ls -aq -f status=exited)
# 【危险!】强制删除所有容器
docker container rm -f $(docker container ls -aq)
不过呢,这个命令替换还是有很多值得注意的地方的
- **如果内部命令输出多行,命令替换默认会将这些输出合并为一个字符串,用空格分隔。**所以上面的例子中,三个容器的 ID 被空格分开,然后作为参数传递给 docker container stop。
- **如果内部命令没有输出,那么命令替换的结果是空,那么外部命令可能就会因为缺少参数而报错。**例如,如果没有运行中的容器,那么 docker container stop $(docker container ls -q) 就会变成 docker container stop,而 stop 命令需要至少一个参数,所以会报错。
- 命令替换中的命令如果执行失败,那么外部命令也会受到影响。
3.2.示例
话不多说,我们直接实战一下

我们先看看它们的状态

很好,都启动了,现在我们停止一个容器mynginx4

我们检查一下它的状态
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40aa5a938cb6 nginx:1.22.0 "/docker-entrypoint...." 3 minutes ago Exited (0) 2 minutes ago mynginx4
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 3 minutes ago Up 3 minutes 80/tcp mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 3 minutes ago Up 3 minutes 80/tcp mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 3 minutes ago Up 3 minutes 80/tcp mynginx1
现在我们就来测验一下
实际上,**docker ps 是 docker container ls 的简写形式。**在早期的 Docker 版本中,我们使用 docker ps 来列出容器。后来,Docker 引入了更明确的命令结构,将命令按功能分组,例如 container、image、network 等。因此,docker container ls 是更现代、更推荐的写法,但 docker ps 仍然被广泛支持和使用。
cpp
root@VM-16-14-ubuntu:~# docker ps -q
613f84699414
f5477340fa83
6c43bc46b679
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Up 16 minutes 80/tcp mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Up 16 minutes 80/tcp mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Up 16 minutes 80/tcp mynginx1
root@VM-16-14-ubuntu:~# docker ps -q
613f84699414
f5477340fa83
6c43bc46b679
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40aa5a938cb6 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Exited (0) 15 minutes ago mynginx4
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Up 16 minutes 80/tcp mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 16 minutes ago Up 16 minutes 80/tcp mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Up 17 minutes 80/tcp mynginx1
root@VM-16-14-ubuntu:~# docker ps -aq
40aa5a938cb6
613f84699414
f5477340fa83
6c43bc46b679
大家仔细比对!!
cpp
root@VM-16-14-ubuntu:~# docker ps -f status=running
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Up 17 minutes 80/tcp mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Up 17 minutes 80/tcp mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Up 17 minutes 80/tcp mynginx1
root@VM-16-14-ubuntu:~# docker ps -f status=exited
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40aa5a938cb6 nginx:1.22.0 "/docker-entrypoint...." 17 minutes ago Exited (0) 16 minutes ago mynginx4
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40aa5a938cb6 nginx:1.22.0 "/docker-entrypoint...." 18 minutes ago Exited (0) 16 minutes ago mynginx4
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 18 minutes ago Up 18 minutes 80/tcp mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 18 minutes ago Up 18 minutes 80/tcp mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 18 minutes ago Up 18 minutes 80/tcp mynginx1
怎么样?还是不错的吧!!接下来我们执行下面这个命令
bash
docker stop $(docker ps -q)

怎么样?
bash
docker start $(docker ps -aq -f status=exited)

现在是不是都启动了?
接下来我们就批量停止

现在我们去看看它们的状态
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40aa5a938cb6 nginx:1.22.0 "/docker-entrypoint...." 2 hours ago Exited (0) 46 seconds ago mynginx4
613f84699414 nginx:1.22.0 "/docker-entrypoint...." 2 hours ago Exited (0) 46 seconds ago mynginx3
f5477340fa83 nginx:1.22.0 "/docker-entrypoint...." 2 hours ago Exited (0) 46 seconds ago mynginx2
6c43bc46b679 nginx:1.22.0 "/docker-entrypoint...." 2 hours ago Exited (0) 46 seconds ago mynginx1
再把它们批量删除
cpp
docker rm $(docker ps -aq -f status=exited)

怎么样?懂了没
四.容器交互模式
4.1.attached模式(前台模式)
Attached 模式(前台模式):在这个模式下,你的终端(命令行窗口)会变成容器主进程的"控制台"。你会在当前终端里直接看到容器的输出,并且可以直接向它发送输入。简单说,你的终端和容器"粘"在了一起。
一个生动的比喻
想象一下,你正在运行一个程序,比如 python app.py:
- 在普通命令行里,你运行它,所有的打印(print)信息都会显示在当前窗口,你可以通过 Ctrl+C 来终止它。
- Attached 模式运行容器,就相当于你把容器内部的这个主进程(比如 python app.py)"嫁接"到了你的终端上。对你而言,感觉就像直接在宿主机上运行那个进程一样。
- 如何进入 Attached 模式?
情况1:这是默认的模式。
当你使用 docker run 命令且没有使用 -d(detach 分离)参数,并且没有使用-i,-t参数时,你就会以 Attached 模式启动容器。
示例 :前台运行的应用
bash
# 运行一个简单的 Python Web 应用
docker run -p 5000:5000 my-python-app
这个应用的日志(例如 "* Running on http://0.0.0.0:5000/")会直接打印在你的终端上。
情况2:真正的附加模式
bash
# 先启动一个长期运行的容器
docker run -d --name my-container ubuntu bash -c "while true; do echo 'tick'; sleep 1; done"
# 然后附加到它
docker attach my-container
-
你可以看到实时输出
-
在某些情况下可以发送输入给主进程
-
按
Ctrl+C会终止主进程
- Attached 模式的特点
实时输出:容器主进程(PID 1)的标准输出(STDOUT)和标准错误(STDERR)会直接显示在你的终端上。这是查看日志最直接的方式。
直接交互:你可以通过键盘向容器的主进程发送输入(STDIN)。这对于交互式程序(如 shell)至关重要。
生命週期绑定:你的终端与容器的生命周期绑定在一起。
- 如果你在终端中按下 Ctrl+C,这个中断信号会发送给容器的主进程,通常会导致容器停止。
- 如果你关闭终端窗口,相当于切断了容器主进程与控制端的连接,根据配置,这也可能导致容器停止。
- 如何退出 Attached 模式而不停止容器?
这是一个非常常见的痛点。你进入了容器的 bash,做了一些操作,然后想退出,但不希望容器停止。
方法:使用"分离序列"
默认的分离序列是 Ctrl+P 然后紧接着 Ctrl+Q(先按住 Ctrl,然后按 P,松开,再按 Q)。
- 作用:这个操作会让你自己从容器的终端中"抽离"出来,返回到宿主机的命令行,而容器会在后台继续运行。
- 注意:这和 Ctrl+C 有本质区别!Ctrl+C 是终止进程,而 Ctrl+P Ctrl+Q 是断开连接。
另一种方式:在启动时就用 Detached 模式
如果你本来就打算让容器在后台运行,最好一开始就使用:
bash
docker run -d -it --name my_container ubuntu:latest /bin/bash
然后使用 docker attach 命令在需要时连接上去。
- docker attach 命令
这个命令是专门用来将你的终端重新附着到一个已经正在运行的容器的 Attached 模式上。
bash
# 首先,在后台启动一个容器
docker run -d --name my_detached_container my-python-app
# 然后,将你的终端附着到它上面
docker attach my_detached_container
执行 docker attach 后,你就能看到那个容器的实时日志了,并且可以与之交互(如果它的主进程接受输入的话)。
退出 docker attach:同样,使用 Ctrl+P Ctrl+Q 可以安全分离,让容器继续运行。使用 Ctrl+C 会向容器主进程发送终止信号。
话不多说,我们直接看例子

现在我们去浏览器访问一下这个网页,我们回去看看

怎么样?是不是打印出一条新的日志了!!!
我们每刷新一次,就会多打印出一条日志

现在我们往里面输入任何字符都没有反应

这个时候我们ctrl+C看看

我们发现它退出了
cpp
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d89ba23f141 nginx:1.22.0 "/docker-entrypoint...." 3 minutes ago Exited (0) 32 seconds ago frosty_solomon
确实是如此。
4.2.detached 模式(后台模式)
Detached模式,顾名思义,就是"分离"模式,也称为后台模式。
在Detached模式下,容器会在后台运行,不会占用当前的终端。
我们通过对比来深入理解。
如何以Detached模式启动容器?
使用-d或--detach选项。
示例:
bash
docker run -d --name my_detached_container nginx
执行这个命令后,终端会打印出容器的ID,然后立即返回,并显示新的命令提示符。这意味着容器已经在后台启动了。
Detached模式的特点
**终端立即返回:**启动容器后,终端不会被占用,你可以继续执行其他命令。
**看不到实时日志:**容器内进程的输出(标准输出和标准错误)不会显示在当前的终端上。
**生命周期与终端无关:**即使你关闭了启动容器时所用的终端,容器也不会停止,它会继续在后台运行。
如何与Detached模式的容器交互?
虽然容器在后台运行,但我们仍然有多种方式与之交互。
1. 查看日志:docker logs
bash
docker logs my_detached_container
你可以通过docker logs命令来查看容器的输出。如果加上-f(follow)选项,可以像Attached模式一样实时查看日志。
bash
docker logs -f my_detached_container
2. 进入容器执行命令:docker exec
如果你想在容器内执行命令,可以使用docker exec。这对于调试、查看容器内部状态非常有用。
例如,进入容器的shell(前提是容器内有shell,比如bash):
bash
docker exec -it my_detached_container /bin/bash
注意:docker exec命令中,-it选项表示交互式终端,这样你才能与容器的shell交互。
执行一个一次性命令(不需要进入交互式shell):
bash
docker exec my_detached_container ls /usr/share/nginx/html
3. 连接到容器的Attached模式:docker attach
你可以使用docker attach命令将终端重新附着到正在后台运行的容器上。
bash
docker attach my_detached_container
但是要注意,一旦你使用docker attach,你就会进入Attached模式,看到容器的输出,并且可以发送输入(如果容器主进程接受输入的话)。同样,要退出Attached模式而不停止容器,可以使用分离序列Ctrl+P Ctrl+Q。如果直接按Ctrl+C,则会停止容器。
注意:如果容器的主进程是一个shell(比如/bin/bash),那么docker attach会连接到这个shell,但你可能会发现它没有响应,因为shell可能正在等待输入。所以,对于交互式容器,通常我们使用docker exec来进入。
如何停止Detached模式的容器?
直接实用docker stop命令
bash
docker stop my_detached_container
如何将已经以Attached模式运行的容器转为Detached模式?
如果你已经以Attached模式启动了一个容器,并且不想停止它,但又想收回终端的控制权,你可以使用分离序列Ctrl+P Ctrl+Q来将容器转为后台运行(即Detached模式)。
反之,如果你启动了一个Detached模式的容器,你可以用docker attach命令将终端附着上去,转为Attached模式。
最佳实践
- 长期运行的服务(如Web服务器、数据库等)通常以Detached模式运行,这样它们不会占用终端,并且可以在后台持续运行。
- 调试和交互式任务(如构建镜像、运行一次性脚本或调试容器内部)通常使用Attached模式或docker exec命令。
注意点
- 以Detached模式启动的容器,其生命周期与启动它的终端无关。这意味着即使终端关闭,容器也会继续运行。
- 默认情况下,容器内的主进程的日志输出(标准输出和标准错误)会被Docker捕获,你可以通过docker logs查看。但请注意,如果日志量很大,可能需要配置日志驱动和日志轮转,以防止磁盘空间被占满。
4.3.interactive模式(交互模式)
第一问:什么是"交互模式"?
想象一下,你买了一台新的电脑(这就是一个容器),但它现在处于关机状态。交互模式,就像是你按下了这台电脑的开机键,并且直接坐在了它的屏幕和键盘前面。
在 Docker 的世界里:
- 容器:就是一个轻量级的、隔离的软件运行环境(可以理解为那台小电脑)。
- 交互模式:就是让你能进入这个容器内部,像一个真正的用户一样,在里面输入命令、执行程序、查看结果。
- 核心思想: 把容器从一个"后台静默运行的进程",变成一个"可以与之对话的临时操作系统"。
第二问:为什么需要它?它解决什么问题?
没有交互模式会怎样?我们来看一个常见的场景。
你想在一个干净的 Ubuntu 容器里随便看看,比如检查一下 ls 命令。如果你直接运行:
bash
docker run ubuntu:latest ls
容器会执行 ls 命令,把根目录列表打印出来,然后任务完成,容器立即退出。你就像让一个机器人帮你拍一张房间的照片,它拍完照、把照片递给你,然后就消失了。你并没有"进入"那个房间。
交互模式解决的问题就是:
- 保持容器运行:不让它执行完一个命令就退出。
- 提供一个人机交互的接口:让你能向容器内部发送命令,并看到它的输出。
第三问:怎么启动交互模式?(核心命令)
启动交互模式,秘诀在于使用两个关键的参数:-i 和 -t。它们通常形影不离,写成 -it。
- -i 或 --interactive:保持标准输入流打开。简单说,就是允许你向容器里输入命令。
- -t 或 --tty:分配一个伪终端。这相当于为你的容器启动了一个"虚拟的屏幕和键盘",让你感觉就像在用一台真实的电脑终端。
经典命令如下:
bash
docker run -it <镜像名> <shell>
最常用的例子,启动一个 Ubuntu 容器并进入:
bash
docker run -it ubuntu:latest /bin/bash
让我们拆解一下这个命令:
- docker run:创建并启动一个新容器。
- -it:开启交互模式和伪终端。
- ubuntu:latest:使用的镜像。
- /bin/bash:容器启动后要运行的命令。这里我们运行的是 Bash shell,它是一个强大的命令行解释器,我们就是通过它来与容器交互的。
第四问:启动后会发生什么?
执行上面的命令后,你的命令行提示符会立刻发生变化!它可能看起来像这样:
bash
root@a1b2c3d4e5f6:/#
这表示你已经成功进入了容器内部!
- root:你现在是容器的 root 用户(超级管理员)。
- @a1b2c3d4e5f6:@ 后面是你的容器 ID。
- :/#:/ 表示你当前在容器的根目录。
现在,你可以像使用一台普通的 Ubuntu 系统一样,执行任何命令:
- ls - 查看当前目录文件
- pwd - 显示当前目录
- cat /etc/os-release - 查看系统信息,确认你确实在容器里
- apt update && apt install -y python3 - 甚至可以安装软件!
第五问:如何退出交互模式?
这里有两个选项,非常重要:
1.退出并停止容器:
- 在容器内部的命令行中,直接输入 exit 或者按 Ctrl + D。
- 效果:Bash shell 会结束,因为这个 shell 是容器的主进程,主进程结束,容器也就随之停止运行了。这就像你把那台小电脑的电源给关了。
2.只退出交互,但保持容器在后台运行:
- 按快捷键 Ctrl + P,然后 Ctrl + Q(先按 Ctrl+P,松开,再按 Ctrl+Q)。
- 效果:你会退回到你宿主机的命令行,但那个容器并没有停止。你可以用 docker ps 命令看到它依然在运行。这就像你从一台虚拟机的屏幕上走开,但虚拟机本身还在后台开着。
- 之后如果你想再次进入这个容器,可以使用:docker exec -it <容器名或ID> /bin/bash
五.容器与宿主机内容复制

接下来我们启动一个容器

现在我们使用浏览器去访问一下这个界面

如果说我们想要编辑这个页面,我们就需要进去看看


这个就是我们界面的代码。我们试一下能不能vim它

可以看到这个镜像里面没有vim这个工具,所以我们可以先在宿主机里面写好了,再拷贝到这里来。

现在我们就把镜像里面的那个index拷贝过来
docker cp mynginx1:/usr/share/nginx/html/index.html .

现在我们使用vim进行修改一下

保存退出,我们去把这个文件拷贝回那个容器里面
docker cp ./index.html mynginx1:/usr/share/nginx/html/index.html

现在我们回去容器进行检查


怎么样?是不是拷贝成功了。
我们回去浏览器刷新一下

怎么样?是不是就成功了。
容器和容器之间能不能进行拷贝?
话不多说,我们先运行一个新的容器

我们现在去浏览器看看

现在我们就把mynginx1的index.html文件拷贝给mynginx2
docker cp mynginx1:/usr/share/nginx/html/index.html mynginx2:/usr/share/nginx/html/index.html
我们一执行,就发现报错了

不,这个命令是不正确的。Docker cp 命令不支持直接在两个容器之间复制文件。
docker cp 命令的语法是:
- 从容器复制到主机:docker cp <container>:<path> <host_path>
- 从主机复制到容器:docker cp <host_path> <container>:<path>
六.容器的自动删除
- --rm:此参数是一个自动化清理选项。它指定当容器退出时,Docker 守护进程将自动删除该容器。这主要用于临时性的测试容器,以避免产生大量停止状态的容器,占用磁盘空间。
-it容器指定--rm选项
docker run -it --rm --name mywebsite1 -p 8081:80 nginx:1.22.0 bash

我们现在打开另外一个终端看看
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2355f475b16 nginx:1.22.0 "/docker-entrypoint...." 28 seconds ago Up 28 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mywebsite1
现在我们回到第一个终端,执行exit

现在我们执行docker ps -a

发现没有一个容器了,这就是--rm在起作用。
-d容器指定--rm选项

现在我们去看看它的状态
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03ffd52873ff nginx:1.22.0 "/docker-entrypoint...." 27 seconds ago Up 26 seconds 0.0.0.0:8082->80/tcp, [::]:8082->80/tcp mywebsite2
现在我们执行下面这个命令
docker stop mywebsite2

现在我们去看看

容器没有了,这就是--rm在起着作用。
所以:生产环境一定要小心使用--rm选项
七.容器的自动重启
--restart 参数是 Docker 容器的高可用性核心配置,它定义了当容器退出后,Docker 守护进程是否以及如何尝试自动重新启动它。
工作原理:Docker 守护进程会监控容器的退出状态。一旦检测到容器退出,它会根据 --restart 策略来决定后续动作。只有设置了此参数的容器,Docker 才会尝试自动重启。
策略选项:
重启策略的类别
no(默认):
- 行为:容器退出后,Docker守护进程不会尝试重启它。容器将保持在退出(Exited)状态。
- 使用场景:适用于一次性任务或不需要自动恢复的容器。
on-failure:
- 行为:只有在容器非正常退出时才会重启。所谓"非正常退出",是指容器的退出状态码(exit code)不为 0(在 Linux 中,0 通常表示成功)。
- 可以可选地指定最大重试次数(例如on-failure:5),当重启尝试超过指定次数后,Docker将放弃重启。
- 使用场景:适用于需要处理临时性错误(如依赖服务暂时不可用)的应用,但希望永久性错误(如应用代码bug)时不再重启。
always:
- 行为:无论容器退出状态如何(包括正常退出和非正常退出),Docker都会无限次地尝试重启容器。
- 但是,如果容器是被docker stop或docker rm命令停止或删除的,则不会重启。
- 注意:当Docker守护进程启动时,如果容器设置为always,那么即使容器之前被停止(除非是手动停止),它也会被启动。
- 实际上,在Docker守护进程启动时,对于always策略的容器,只要不是被用户明确停止的(即通过docker stop停止的),都会被重启。但是,注意always和unless-stopped的区别。
- 使用场景:适用于需要持续运行的服务,即使服务正常退出(例如完成了一个任务,但需要立即再次运行)也需要重启的情况。但注意,如果容器正常退出,使用always会导致不断重启,可能并不适合所有场景。
unless-stopped:
- 行为:与always类似,无论容器退出状态如何(包括正常退出和非正常退出),Docker都会无限次地尝试重启容器。
- 但是有一个关键区别:**如果容器是被手动停止(即通过docker stop命令),那么即使Docker守护进程重启,该容器也不会被自动启动。**也就是说,unless-stopped尊重用户手动停止容器的操作,并记住这个状态。
- 使用场景:适用于需要持续运行的服务,但同时允许用户手动停止容器并希望该状态在Docker守护进程重启后得以保持。
例子:
docker run --restart no my-once-off-script
这两条是等价的
docker run my-once-off-script
# 只要因为错误退出就无限重启
docker run --restart on-failure my-web-api
# 最多尝试重启5次
docker run --restart on-failure:5 my-web-api
测试1------测试always
我们先启动一个容器

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
27fee1645e24 nginx:1.22.0 "/docker-entrypoint...." 2 seconds ago Up 2 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mywebsite1
我们可以看看重启策略
docker container inspect mywebsite1

这给非常清楚了。
现在我们使用docker ps查看一下

现在我们去停止这个容器

可以看到这个其实是退出码是0的情况。
这个时候我们再去使用docker ps查看一下,发现它的状态变化了

这就说明它重启过了。
接下来我们试一下docker stop能不能触发重启

我们使用docker ps -a看看

很明显这个always不能重启这个手动停止的。
测试2------测试测试always和unless-stopped的相同点
首先我们先运行两个容器
docker run -d --name always-container --restart=always nginx:1.22.0
docker run -d --name unless-stopped-container --restart=unless-stopped nginx:1.22.0

接下来我们执行下面这些命令

我们回去查看一下它们的状态

发现了没,都自动进行重启了。
现在我们将docker 守护进程进行重启,看看它们是不是会自动进行重启啊
重启Docker守护进程(注意:这会影响所有容器)
bash
systemctl restart docker # 或者重启Docker服务
systemctl status docker

步骤4:检查容器状态
bash
docker ps -a
我们看看
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e0cab99cdbf nginx:1.22.0 "/docker-entrypoint...." 11 minutes ago Up 30 seconds 80/tcp unless-stopped-container
79857c3ef4d7 nginx:1.22.0 "/docker-entrypoint...." 11 minutes ago Up 30 seconds 80/tcp always-container

都进行重启了啊!!
在 Docker 守护进程重启的场景下,能够导致容器自动重新启动的策略包括:
- always - 总是重新启动
- unless-stopped - 只有非手动停止的容器会重新启动
- 而 no 和 on-failure 策略在这种情况下不会触发自动重启。
测试3------测试always和unless-stopped的区别(手动停止)
步骤1:创建两个容器,分别使用always和unless-stopped策略
docker run -d --name always-container --restart=always nginx:1.22.0
docker run -d --name unless-stopped-container --restart=unless-stopped nginx:1.22.0

步骤2:使用docker stop停止这两个容器
docker stop always-container
docker stop unless-stopped-container


我们使用docker ps -a查看一下

步骤3:重启Docker守护进程(注意:这会影响所有容器)
bash
systemctl restart docker # 或者重启Docker服务
systemctl status docker

步骤4:检查容器状态
bash
docker ps -a
我们看看
cpp
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e0cab99cdbf nginx:1.22.0 "/docker-entrypoint...." 2 minutes ago Exited (0) 2 minutes ago unless-stopped-container
79857c3ef4d7 nginx:1.22.0 "/docker-entrypoint...." 2 minutes ago Up 46 seconds 80/tcp always-container
我们发现,只有这个always策略的容器重启了,而这个unless-stopped策略的居然没有进行重启!
注意:实际上,在Docker守护进程重启后,它会检查容器的重启策略和当前状态。
- 对于always,它会重启所有容器(即使之前是被docker stop停止的)。
- 而对于unless-stopped,他也会所有重启容器,只不过它不会重启那些被手动停止的容器。
因此,如果你希望一个容器在Docker守护进程重启时总是被启动,即使它之前被docker stop停止了,那么使用always。但通常情况下,我们更希望手动停止的容器保持停止状态,这时应该使用unless-stopped。
另外,注意:如果容器是因为宿主机重启而停止的(即Docker守护进程随着宿主机重启而重启),那么:
对于always和unless-stopped,容器都会在Docker守护进程启动时被启动,除非这个容器在宿主机重启前已经被手动停止了(unless-stopped会记住手动停止的状态,而always不会)。
八.容器的环境变量设置
在 Docker 中,环境变量是向容器传递配置的一种常见方式。有两种主要方法:使用 -e 或 --env 标志直接设置变量,以及使用 --env-file 从文件加载多个变量。
方式一:使用多个-e选项来配置环境变量
我们先看看第一种设置多个环境变量的方式
cpp
docker run -it --rm -e MYTEST1=1 -e MYTEST2=2 -e MYTEST3=3 nginx:1.22.0 bash

方式二:通过配置文件来配置环境变量

现在我们在这里创建一个配置文件
cpp
vim myenv

cpp
docker run -it --rm --env-file=./myenv nginx:1.22.0 bash

九.容器详情查看
首先我们先运行起来一个容器
cpp
docker run -d --name mynginx1 -p 8081:80 -e MYTEST=1 -h mynginx.com nginx:1.22.0

现在我们就去查看一下它的信息
cpp
docker container inspect mynginx1

可以说是非常简单的啊!!
十.借助容器执行某些特殊任务
我们可以直接借助docker的容器环境执行一些命令,比如容器中有某个命令而宿主机 上没有这个时候借助容器可以完成某些任务。

这个其实是容器的ip,我们看一下宿主机的ip


这个其实是非常常用的。
十一.容器的导入导出
首先我们先启动一个容器,
cpp
docker run -d --name mynginx1 -p 8081:80 nginx:1.22.0

我们现在去浏览器看看

接下来我们进入容器内部去修改一下主页的内容
cpp
docker exec -it mynginx1 bash

cpp
echo "I am from bit docker" > index.html

我们现在回去浏览器看看

这个还是很符合预期的。

现在我们就把上面这个容器打包成一个.tar文件
cpp
docker export -o mynginx1.tar mynginx1

现在就完成导出了吧。
现在我们就把这个.tar文件还原成一个镜像
cpp
docker import mynginx1.tar mynginx1:v1.0

还是很不错的吧,现在我们就基于这个镜像来启动一个新的容器。
cpp
docker run -d --name mynginx2 -p 8082:80 mynginx1:v1.0

我们发现报错了啊,这是是因为我们将容器保存为.tar文件时,会丢失一些元数据
cpp
docker inspect mynginx1:v1.0

这个启动命令变成了null了。
我们可以看看我们最初的镜像的启动命令是啥?
cpp
docker inspect nginx:1.22.0

其实不止这个,还有很多别的属性也都丢失了
可以看到啊,使用这个.tar包的缺点就是会丢失一些元数据啊。
那么我们怎么启动这个容器呢?
cpp
docker run -d --name mynginx2 -p 8082:80 mynginx1:v1.0 nginx -g "daemon off;"

我们现在再去浏览器看看

怎么样?是不是成功了。
十二.容器日志的查看
cpp
docker run -d --name mynginx1 -p 8081:80 nginx:1.22.0

接下来我们可以查看它的日志
cpp
docker logs mynginx1

可以看到,一运行起来就退出了。不能实时更新,如果说想要实时更新,就需要使用-f参数
cpp
docker logs -f mynginx1

我们去浏览器多刷新几下

就会多打印出几个这个

实时刷新。如果说你觉得显示的日志的数量太多了,那么我们就带上-n选项来指定只显示最新的几条
cpp
docker logs -n 5 -f mynginx1

我们去浏览器刷新几次

这个其实还是很简单的。
现在我们需要把这个日志放到一个文件里面,其实是有两个做法的
- 重定向
- 使用docker官方内部的日志
方法一:重定向
cpp
docker logs mynginx1 > info.log 2> err.log
这个会把标准输出流输出到info.log,把这个标准错误流输出到err.log



还是很不错的吧
方法二:使用docker官方的内部记录的日志
首先我们先执行下面这个命令
cpp
docker info
找到下面这一行

这个/var/lib/docker就是docker的数据目录

我们去它的containers子目录看看
cpp
root@VM-16-14-ubuntu:~# ls -l /var/lib/docker/containers
total 4
drwx--x--- 4 root root 4096 Nov 2 14:56 793cc3851a6f322bb6274ab2454b5d2a0b3086a1f5d17e2ebe9354c354ccb464

可以看到这里有一个目录啊,这个目录怎么是一堆乱七八糟的数字啊,其实这个就是我们容器的ID
cpp
root@VM-16-14-ubuntu:~# docker ps --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
793cc3851a6f322bb6274ab2454b5d2a0b3086a1f5d17e2ebe9354c354ccb464 nginx:1.22.0 "/docker-entrypoint.sh nginx -g 'daemon off;'" 16 minutes ago Up 16 minutes 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mynginx1
看到了吧,是不是完全对上了!

我们进去看看
这里有这个793cc3851a6f322bb6274ab2454b5d2a0b3086a1f5d17e2ebe9354c354ccb464-json.log,这个就是docker内部记录的日志

如果说,我们需要这个日志,只需拷贝出去即可。
十三.容器资源的查看
话不多说,我们直接先运行一个容器再说


现在我们就来监控整个容器的资源的使用
cpp
docker stats mynginx1

现在我们打开浏览器,疯狂刷新

可以看到这些资源都在上升啊!
十四.综合实战一------Mysql容器安装使用
首先我们需要先去docker hub官网寻找这个mysql的镜像

点进去看到

我们往下面翻,发现就有怎么使用它的方法

我们现在就来,首先我们先拉取一下镜像


现在我们就根据这个来启动镜像
docker run --name mysql1 -e MYSQL_ROOT_PASSWORD=123456 -p 8201:3306 -d mysql:8.0.42

我们看一下它的状态
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73b429ced4a3 mysql:8.0.42 "docker-entrypoint.s..." 59 seconds ago Up 59 seconds 33060/tcp, 0.0.0.0:8201->3306/tcp, [::]:8201->3306/tcp mysql1
很明显,我们运行起来了。
现在是运行起来了,那么我们要是想要登录这个mysql进程该怎么做?
docker exec -it mysql1 bash

怎么样?是不是就登录进来了。



我们发现,使用起来完全没有一点问题。
就跟安装在自己电脑上一样。

我们退出来之后,这个进程还在运行
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73b429ced4a3 mysql:8.0.42 "docker-entrypoint.s..." 9 minutes ago Up 9 minutes 33060/tcp, 0.0.0.0:8201->3306/tcp, [::]:8201->3306/tcp mysql1
还是很不错的吧。
我们可以尝试一下跨主机访问这个mysql
mysql -h 主机ip -P 8201 -u root -p
我们使用windows上面的mysql来访问一下我们的mysql

我们发现这个远程登陆完全没有任何问题。
十五.综合实战二------Redis容器安装使用
Redis是什么我不想多说。我只想讲解安装使用
还是去docker hub官网先寻找到我们需要的镜像


我们这里拉取redis 8.0

现在我们就来启动redis容器
docker run --name redis1 -p 8300:6379 -d redis:8.0

查看一下它的状态
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb127d956fb6 redis:8.0 "docker-entrypoint.s..." 20 seconds ago Up 19 seconds 0.0.0.0:8300->6379/tcp, [::]:8300->6379/tcp redis1
很好,已经运行起来了。
接下来我们执行下面这个
docker exec -it redis1 bash

很完美吧!!
接下来我们需要测试远程连接这个redis服务器
这个需要一个新的可视化工具:AnotherRedisDesktopManager 发行版 - Gitee.com




输入IP地址和端口号,然后点击OK即可。
然后我们就会看到下面这个

可以看到右边的1了吗?那就是它的值。
我们现在回原来云服务器执行下面这个

现在我们回去这个客户端看看

看到了没,左边就是键!!它也更新了,我们去看看


都对上了,远程登陆没有问题啊!!
十六.综合实战三------C++容器制作
首先我们需要拉取一个ububtu镜像

现在我们就启动这个容器
docker run -it --name mycpp ubuntu:22.04 bash

启动之后,我们需要修改Ubuntu系统的软件源配置文件
sudo sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list
apt update

现在我们就能安装一些软件了
apt install gcc vim g++ -y
我们这里先安装gcc,g++,vim
mkdir src
cd src
vim main.cpp
我们在main.cpp里面写下面这个
#include<iostream>
using namespace std;
int main()
{
cout<<"hello docker"<<endl;
}
我们进行编译一下
g++ -o test main.cpp

后续我们再把这个容器打包成一个镜像,再进行一些简单的操作,就能把这个做成镜像发布出去了。只不过我们在这里不能好好讲讲,我们后续会专门写几篇文章来详细讲解如何制作镜像的。