docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > Docker容器操作

Docker容器操作和大量实用案例(含详细图文)

作者:掘根

Docker作为一种开源的容器化平台,能够简化应用程序的打包、分发和运行过程,这篇文章主要介绍了Docker容器操作和大量实用案例的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下

前言

我们在上一篇文章里面讲了很多的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版本的。

执行完后我们看看

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

容器也正常运行起来了!!还行不,接下来我们去浏览器看看

http://150.158.139.86:8081/

我们可以获取这个容器的更多信息

docker inspect mynginx001

docker inspect会自动识别mynginx001是镜像还是容器

……

这里有很多信息,我不想多说。

其实我们也可以查看一下这个容器的日志

docker logs -f -n 5 mynginx001

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

怎么样?日志是不是变多了!!

我们接着往下面看

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

我们现在需要删掉这个容器

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

非常的完美了吧!!

二.容器的状态迁移

先看本地的镜像

接下来我们就执行下面这个命令

docker create --name myginx002 -p 8002:80 nginx:1.22.0

我们查看一下它的状态

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

接下来我们就启动这个容器

docker start myginx002

我们去看看它的状态

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

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

docker kill myginx002

现在我们去观察一下这个容器的状态

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

状态变成了下面这样子

现在我们继续启动这个容器

docker start myginx002

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

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

docker stop myginx002

我们查看一下状态

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

我们看看它的状态

现在我们接着重新启动我们的容器

docker start myginx002

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

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

docker restart 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 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

状态变化还是很明显的

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

现在还是可以正常刷新的!!!

执行下面这个命令

docker pause myginx002

现在我们去查看一下它的状态

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!!

现在我们回去浏览器,点击刷新,发现一直就是刷新不了了,但是原来的界面还在

现在我们执行下面这个命令

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)是做什么的。

现在,我们来深入理解你列出的这些“调味品”(参数),它们能让 docker container ls 这道“主菜”变得更符合你的口味。

3.1.1. 基础参数:-a 和 -q

-a:显示所有容器。

命令示例:

# 只查看正在运行的容器
docker container ls
# 查看所有容器(包括已停止的)
docker container ls -a

-q:静默模式,只返回容器 ID。

命令示例:

# 查看所有容器的详细信息
docker container ls -a
# 只获取所有容器的 ID(注意:包括已停止的)
docker container ls -aq

3.1.2. 过滤参数:-f 或 --filter

基本语法:

docker container ls --filter "<属性键>=<属性值>"
# 或者使用短格式
docker container ls -f "<属性键>=<属性值>"

工作原理:当你使用 --filter 时,Docker 会:

让我们来深入理解你列出的以及几个最常用的属性键

1. 按状态过滤:status

这是最常用的过滤器之一。

作用:根据容器的运行状态来筛选。

常用值:

示例:

# 只显示正在运行的容器
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。

# 查找名字中包含 "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' 镜像(任何标签)创建的容器
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"

4. 按标签过滤:label

示例:

# 假设你运行容器时这样打标签:
# 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"。

如果我们这样写:

echo $(echo "Hello")

那么执行步骤是:

先执行 echo "Hello",得到输出 "Hello"。

然后将 $(echo "Hello") 替换为 "Hello",所以整个命令变成了:

echo "Hello"

然后执行这个命令,最后输出 "Hello"。

看起来好像多此一举,但实际上,命令替换的真正威力在于,它可以让一个命令的输出作为另一个命令的参数。

事实上,这个在在 Docker 中的实际应用其实是非常广泛的

示例一:停止所有正在运行的容器

在 Docker 中,我们经常需要处理多个容器。

比如,我们想停止所有正在运行的容器。

没有命令替换的做法:

这样做很麻烦,而且如果容器很多,很容易出错。

使用命令替换的做法:

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 的输出可能是:

a1b2c3d4e5f6
x1y2z3u4v5w6
k9l8m7n6o5p4

然后,命令替换会发生,$(docker container ls -q) 会被替换为这三个 ID,整个命令变成:

docker container stop a1b2c3d4e5f6 x1y2z3u4v5w6 k9l8m7n6o5p4

最后,Shell 执行这个命令,停止这三个容器。

这样,我们只需要一行命令就可以停止所有运行中的容器,而不需要手动输入每个容器的 ID。

另一个例子:删除所有已退出的容器

我们经常需要清理已经退出的容器。我们可以这样写:

docker container rm $(docker container ls -aq -f status=exited)

分解:

docker container ls -aq -f status=exited:

假设这个命令输出两个已退出容器的 ID:

c1
c2

然后命令替换会发生,整个命令变成:

docker container rm c1 c2

命令替换的注意事项

 当然看了上面2个例子,我们应该就能看懂下面这个了吧

# 停止所有运行中的容器
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)

不过呢,这个命令替换还是有很多值得注意的地方的

3.2.示例

话不多说,我们直接实战一下

我们先看看它们的状态

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

我们检查一下它的状态

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 仍然被广泛支持和使用。

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

大家仔细比对!!

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

怎么样?还是不错的吧!!接下来我们执行下面这个命令

docker stop $(docker ps -q)

怎么样?

docker start $(docker ps -aq -f status=exited)

现在是不是都启动了?

接下来我们就批量停止

现在我们去看看它们的状态

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

再把它们批量删除

docker rm $(docker ps -aq -f status=exited)

怎么样?懂了没

四.容器交互模式

4.1.attached模式(前台模式)

Attached 模式(前台模式):在这个模式下,你的终端(命令行窗口)会变成容器主进程的“控制台”。你会在当前终端里直接看到容器的输出,并且可以直接向它发送输入。简单说,你的终端和容器“粘”在了一起。

一个生动的比喻

想象一下,你正在运行一个程序,比如 python app.py:

1. 如何进入 Attached 模式?

情况1:这是默认的模式。

当你使用 docker run 命令且没有使用 -d(detach 分离)参数,并且没有使用-i,-t参数时,你就会以 Attached 模式启动容器。

示例 :前台运行的应用

# 运行一个简单的 Python Web 应用
docker run -p 5000:5000 my-python-app

这个应用的日志(例如 “* Running on http://0.0.0.0:5000/”)会直接打印在你的终端上。

情况2:真正的附加模式

# 先启动一个长期运行的容器
docker run -d --name my-container ubuntu bash -c "while true; do echo 'tick'; sleep 1; done"
# 然后附加到它
docker attach my-container

2. Attached 模式的特点

实时输出:容器主进程(PID 1)的标准输出(STDOUT)和标准错误(STDERR)会直接显示在你的终端上。这是查看日志最直接的方式。

直接交互:你可以通过键盘向容器的主进程发送输入(STDIN)。这对于交互式程序(如 shell)至关重要。

生命週期绑定:你的终端与容器的生命周期绑定在一起。

3. 如何退出 Attached 模式而不停止容器?

这是一个非常常见的痛点。你进入了容器的 bash,做了一些操作,然后想退出,但不希望容器停止。

方法:使用“分离序列”

默认的分离序列是 Ctrl+P 然后紧接着 Ctrl+Q(先按住 Ctrl,然后按 P,松开,再按 Q)。

另一种方式:在启动时就用 Detached 模式

如果你本来就打算让容器在后台运行,最好一开始就使用:

docker run -d -it --name my_container ubuntu:latest /bin/bash

然后使用 docker attach 命令在需要时连接上去。

4. docker attach 命令

这个命令是专门用来将你的终端重新附着到一个已经正在运行的容器的 Attached 模式上。

# 首先,在后台启动一个容器
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看看

我们发现它退出了

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选项。

示例:

docker run -d --name my_detached_container nginx

执行这个命令后,终端会打印出容器的ID,然后立即返回,并显示新的命令提示符。这意味着容器已经在后台启动了。

Detached模式的特点

终端立即返回:启动容器后,终端不会被占用,你可以继续执行其他命令。

看不到实时日志:容器内进程的输出(标准输出和标准错误)不会显示在当前的终端上。

生命周期与终端无关:即使你关闭了启动容器时所用的终端,容器也不会停止,它会继续在后台运行。

如何与Detached模式的容器交互?

虽然容器在后台运行,但我们仍然有多种方式与之交互。

1. 查看日志:docker logs

docker logs my_detached_container

你可以通过docker logs命令来查看容器的输出。如果加上-f(follow)选项,可以像Attached模式一样实时查看日志。

docker logs -f my_detached_container

2. 进入容器执行命令:docker exec

如果你想在容器内执行命令,可以使用docker exec。这对于调试、查看容器内部状态非常有用。

例如,进入容器的shell(前提是容器内有shell,比如bash):

docker exec -it my_detached_container /bin/bash

注意:docker exec命令中,-it选项表示交互式终端,这样你才能与容器的shell交互。

执行一个一次性命令(不需要进入交互式shell):

docker exec my_detached_container ls /usr/share/nginx/html

3. 连接到容器的Attached模式:docker attach

你可以使用docker attach命令将终端重新附着到正在后台运行的容器上。

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命令

docker stop my_detached_container

如何将已经以Attached模式运行的容器转为Detached模式?

如果你已经以Attached模式启动了一个容器,并且不想停止它,但又想收回终端的控制权,你可以使用分离序列Ctrl+P Ctrl+Q来将容器转为后台运行(即Detached模式)。

反之,如果你启动了一个Detached模式的容器,你可以用docker attach命令将终端附着上去,转为Attached模式。

最佳实践

注意点

  1. 以Detached模式启动的容器,其生命周期与启动它的终端无关。这意味着即使终端关闭,容器也会继续运行。
  2. 默认情况下,容器内的主进程的日志输出(标准输出和标准错误)会被Docker捕获,你可以通过docker logs查看。但请注意,如果日志量很大,可能需要配置日志驱动和日志轮转,以防止磁盘空间被占满。

4.3.interactive模式(交互模式)

第一问:什么是“交互模式”?

想象一下,你买了一台新的电脑(这就是一个容器),但它现在处于关机状态。交互模式,就像是你按下了这台电脑的开机键,并且直接坐在了它的屏幕和键盘前面。

在 Docker 的世界里:

第二问:为什么需要它?它解决什么问题?

没有交互模式会怎样?我们来看一个常见的场景。

你想在一个干净的 Ubuntu 容器里随便看看,比如检查一下 ls 命令。如果你直接运行:

docker run ubuntu:latest ls

容器会执行 ls 命令,把根目录列表打印出来,然后任务完成,容器立即退出。你就像让一个机器人帮你拍一张房间的照片,它拍完照、把照片递给你,然后就消失了。你并没有“进入”那个房间。

交互模式解决的问题就是:

第三问:怎么启动交互模式?(核心命令)

启动交互模式,秘诀在于使用两个关键的参数:-i 和 -t。它们通常形影不离,写成 -it。

经典命令如下:

docker run -it <镜像名> <shell>

最常用的例子,启动一个 Ubuntu 容器并进入:

docker run -it ubuntu:latest /bin/bash

让我们拆解一下这个命令:

第四问:启动后会发生什么?

执行上面的命令后,你的命令行提示符会立刻发生变化!它可能看起来像这样:

root@a1b2c3d4e5f6:/#

这表示你已经成功进入了容器内部!

现在,你可以像使用一台普通的 Ubuntu 系统一样,执行任何命令:

第五问:如何退出交互模式?

这里有两个选项,非常重要:

1.退出并停止容器:

2.只退出交互,但保持容器在后台运行:

五.容器与宿主机内容复制

接下来我们启动一个容器

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

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

这个就是我们界面的代码。我们试一下能不能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 命令的语法是:

六.容器的自动删除

-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(默认):

on-failure:

always:

unless-stopped:

例子:

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守护进程(注意:这会影响所有容器)

systemctl restart docker # 或者重启Docker服务
systemctl status docker

步骤4:检查容器状态

docker ps -a

我们看看

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 守护进程重启的场景下,能够导致容器自动重新启动的策略包括:

测试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守护进程(注意:这会影响所有容器)

systemctl restart docker # 或者重启Docker服务
systemctl status docker

步骤4:检查容器状态

docker ps -a

我们看看

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守护进程重启后,它会检查容器的重启策略和当前状态。

因此,如果你希望一个容器在Docker守护进程重启时总是被启动,即使它之前被docker stop停止了,那么使用always。但通常情况下,我们更希望手动停止的容器保持停止状态,这时应该使用unless-stopped。

另外,注意:如果容器是因为宿主机重启而停止的(即Docker守护进程随着宿主机重启而重启),那么:

对于always和unless-stopped,容器都会在Docker守护进程启动时被启动,除非这个容器在宿主机重启前已经被手动停止了(unless-stopped会记住手动停止的状态,而always不会)。

八.容器的环境变量设置

在 Docker 中,环境变量是向容器传递配置的一种常见方式。有两种主要方法:使用 -e 或 --env 标志直接设置变量,以及使用 --env-file 从文件加载多个变量。

方式一:使用多个-e选项来配置环境变量

我们先看看第一种设置多个环境变量的方式

docker run -it --rm -e MYTEST1=1 -e MYTEST2=2 -e MYTEST3=3 nginx:1.22.0 bash

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

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

vim myenv

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

九.容器详情查看

首先我们先运行起来一个容器

docker run -d --name mynginx1 -p 8081:80 -e MYTEST=1 -h mynginx.com nginx:1.22.0

现在我们就去查看一下它的信息

docker container inspect mynginx1

可以说是非常简单的啊!!

十.借助容器执行某些特殊任务

我们可以直接借助docker的容器环境执行一些命令,比如容器中有某个命令而宿主机 上没有这个时候借助容器可以完成某些任务。

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

这个其实是非常常用的。

十一.容器的导入导出

首先我们先启动一个容器,

docker run -d --name mynginx1 -p 8081:80 nginx:1.22.0

我们现在去浏览器看看

接下来我们进入容器内部去修改一下主页的内容

docker exec -it mynginx1 bash

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

我们现在回去浏览器看看

这个还是很符合预期的。

现在我们就把上面这个容器打包成一个.tar文件

docker export -o mynginx1.tar mynginx1

现在就完成导出了吧。

现在我们就把这个.tar文件还原成一个镜像

docker import mynginx1.tar mynginx1:v1.0

还是很不错的吧,现在我们就基于这个镜像来启动一个新的容器。

docker run -d --name mynginx2 -p 8082:80 mynginx1:v1.0

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

docker inspect mynginx1:v1.0

这个启动命令变成了null了。

我们可以看看我们最初的镜像的启动命令是啥?

docker inspect nginx:1.22.0

其实不止这个,还有很多别的属性也都丢失了

可以看到啊,使用这个.tar包的缺点就是会丢失一些元数据啊。

那么我们怎么启动这个容器呢?

docker run -d --name mynginx2 -p 8082:80 mynginx1:v1.0 nginx -g "daemon off;"

我们现在再去浏览器看看

怎么样?是不是成功了。

十二.容器日志的查看

docker run -d --name mynginx1 -p 8081:80 nginx:1.22.0

接下来我们可以查看它的日志

docker logs mynginx1

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

docker logs -f mynginx1

我们去浏览器多刷新几下

就会多打印出几个这个

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

docker logs -n 5 -f mynginx1

我们去浏览器刷新几次

这个其实还是很简单的。

现在我们需要把这个日志放到一个文件里面,其实是有两个做法的

  1. 重定向
  2. 使用docker官方内部的日志

方法一:重定向

docker logs mynginx1 > info.log 2> err.log

这个会把标准输出流输出到info.log,把这个标准错误流输出到err.log

还是很不错的吧

方法二:使用docker官方的内部记录的日志

首先我们先执行下面这个命令

docker info

找到下面这一行

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

我们去它的containers子目录看看

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

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内部记录的日志

如果说,我们需要这个日志,只需拷贝出去即可。

十三.容器资源的查看

话不多说,我们直接先运行一个容器再说

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

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

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

总结

到此这篇关于Docker容器操作和大量实用案例的文章就介绍到这了,更多相关Docker容器操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文