第3章:Docker 容器 - 动态的运行实例

第3章:Docker 容器 - 动态的运行实例

我们已经成功地使用 Dockerfile 为我们的 Node.js 应用构建了一个名为 my-app:1.0 的镜像。现在,这张"图纸"已经备好,是时候根据它来建造一所能对外提供服务的"房子"------也就是运行一个容器了。

本章,我们将深入学习 docker run 命令的各种强大参数,并掌握管理容器整个生命周期的核心技能。

3.1 [实战] 将我们的 Web 应用以容器形式运行起来

还记得我们在 Dockerfile 里用 EXPOSE 8080 指令声明了容器会监听 8080 端口吗?这就像是在房间里装了一部电话,分机号是8080,但外界并不知道总机号码,还是打不进来。

我们需要做一个端口映射 (Port Mapping) ,把主机(你的电脑)的一个端口,映射到容器的这个 8080 端口上。这样,所有访问你电脑特定端口的流量,都会被 Docker 自动转发到容器内部。

在命令行中执行以下命令:

bash 复制代码
docker run -p 4000:8080 my-app:1.0
  • docker run: 运行容器的命令。
  • -p 4000:8080: 这就是端口映射的关键。-p--publish 的缩写。它的格式是 <host_port>:<container_port>。这条命令的意思是,将主机的 4000 端口,映射到容器的 8080 端口。
  • my-app:1.0: 指定我们要运行哪个镜像。

命令执行后,你会看到和 node app.js 一样的输出 Running on http://0.0.0.0:8080。但这次,它是在一个隔离的容器环境中运行的!

现在,打开你的浏览器,访问 http://localhost:4000

你应该能看到页面上显示出 "Hello, Docker World! This is our first image."。

成功了! 你已经通过主机的端口,访问到了容器内部运行的 Web 服务。

但是,你会发现你的命令行窗口被这个容器的日志占用了,你无法再输入其他命令。要停掉它,你只能按 Ctrl + C。有没有办法让它在后台安静地运行呢?

3.2 docker run 命令的高级用法

docker run 是最核心的命令,它有许多强大的选项,可以让我们更灵活地控制容器。

后台运行 (Detached Mode)

要让容器在后台运行,我们只需要添加 -d--detach 参数。

我们先按 Ctrl + C 停掉刚才的容器,然后执行新命令:

bash 复制代码
docker run -d -p 4000:8080 my-app:1.0

这次,命令执行后,它不会打印应用日志,而是直接输出一长串十六进制的字符串。这个字符串是这个容器的唯一ID。你的命令行也立刻恢复了正常。

现在,再次访问 http://localhost:4000,你会发现应用依然在正常运行。

给容器起个名字

每次都用那一长串的ID来操作容器,实在太不方便了。我们可以用 --name 参数在启动时给容器起一个好记的名字。

bash 复制代码
# 先停掉并删除之前的容器,因为名字不能重复
# (我们会在 3.3 节详细讲解 stop 和 rm 命令)
docker stop <container_id>
docker rm <container_id>

# 启动一个有名字的容器
docker run -d -p 4000:8080 --name web-server my-app:1.0

现在,我们就可以用 web-server 这个名字来代替那串长长的ID了。

3.3 容器的生命周期管理

容器启动后,我们还需要对它进行管理,比如查看状态、停止、重启或删除。

  • 查看正在运行的容器:

    bash 复制代码
    docker ps
    # 或者 docker container ls

    这个命令会列出所有正在运行的容器,以及它们的基本信息,如容器ID、所用镜像、启动命令、创建时间、状态、端口映射和容器名。

  • 查看所有容器(包括已停止的):

    bash 复制代码
    docker ps -a

    你会看到一些 Exited 状态的容器,这些是你之前用 Ctrl + C 停掉或者运行出错的容器。

  • 停止一个容器:

    bash 复制代码
    # 使用名字或ID的前几位都可以
    docker stop web-server

    stop 命令会向容器发送一个信号,让它优雅地停止。

  • 启动一个已停止的容器:

    bash 复制代码
    docker start web-server
  • 删除一个容器 : 注意: 只有停止状态的容器才能被删除。

    bash 复制代码
    docker rm web-server

    如果你想强制删除一个正在运行的容器,可以加上 -f 参数:docker rm -f web-server

  • 查看容器日志: 对于后台运行的容器,我们如何看到它的输出呢?

    bash 复制代码
    docker logs web-server

    如果你想实时跟踪日志(像 tail -f 一样),可以加上 -f 参数:docker logs -f web-server

3.4 如何"进入"一个正在运行的容器?(exec)

有时候,我们需要进入容器内部,去看看文件系统,或者执行一些临时的调试命令。docker exec 命令就是为此而生的。

docker exec 允许你在一个正在运行的容器内,执行一个新命令。

最常见的用法是启动一个交互式的 shell(比如 bashsh):

bash 复制代码
# 确保你的 web-server 容器正在运行
docker start web-server

# -it 参数是关键:
# -i (interactive): 保持标准输入打开,允许你进行交互
# -t (tty): 分配一个伪终端
docker exec -it web-server /bin/sh

执行后,你会发现你的命令行提示符变了,类似 /usr/src/app #。这表示你已经成功进入了 web-server 容器的内部,并且当前位于我们在 Dockerfile 中设置的 WORKDIR

现在,你可以像在普通 Linux 环境中一样操作了:

  • 输入 ls -l,你会看到我们的 app.js, package.json 等文件。
  • 输入 cat app.js,可以查看应用代码。
  • 输入 ps aux,可以看到正在运行的 node app.js 进程。

要退出容器,只需输入 exit 或按 Ctrl + D

3.5 本章小结 & 避坑指南

你现在已经完全掌握了如何驾驭一个 Docker 容器。

  • 本章回顾

    • 我们学会了使用 -p 参数进行端口映射,让外部可以访问容器内的服务。
    • 我们学会了使用 -d--name 参数,让容器后台运行 并拥有一个自定义的名字
    • 我们掌握了容器的生命周期管理 命令:ps, start, stop, rm, logs
    • 我们学会了使用 docker exec 这个强大的工具,进入容器内部进行调试。
  • 避坑指南:端口冲突怎么办?

    • 问题 :执行 docker run -p 4000:8080 ... 时,报错 Error starting userland proxy: listen tcp4 0.0.0.0:4000: bind: address already in use
    • 原因 :这个错误明确地告诉你,你主机上的 4000 端口已经被其他程序占用了。Docker 无法监听一个已经被占用的端口。
    • 排查
      1. 你是不是已经启动了一个一模一样的容器,忘了关?用 docker ps 检查一下。
      2. 你电脑上是不是有其他开发工具(比如另一个Web服务)也正在使用 4000 端口?
    • 解决
      1. 停掉占用端口的那个容器或程序。

      2. 更简单的方法是 :换一个主机的端口号!比如,改成 5000

        bash 复制代码
        docker run -d -p 5000:8080 --name web-server-2 my-app:1.0

        现在,你就可以通过 http://localhost:5000 来访问了。 核心要点 :容器内的端口(8080)是由 Dockerfile 决定的,通常不轻易改变。而主机的端口,你可以根据实际情况随意选择一个未被占用的即可。

我们的应用已经能跑起来了,但还有一个致命问题:如果容器被删除了,应用产生的所有数据(比如用户上传的文件、数据库记录)都会丢失。下一章,我们将学习如何解决这个问题,为容器装上"记忆硬盘"------数据卷。

相关推荐
失散134 小时前
分布式专题——18 Zookeeper选举Leader源码剖析
java·分布式·zookeeper·云原生·架构
胡斌附体5 小时前
linux docker 数据迁移
linux·docker·存储·迁移·rsync保留权限复制
爱敲代码的TOM5 小时前
微服务基础2-网关路由
微服务·云原生·架构
码路工人5 小时前
第2章:Docker 镜像 - 应用的标准化封装
docker·云原生·容器
狮子也疯狂5 小时前
【保姆级】| 基于Docker的dify部署流程
运维·docker·容器
KubeSphere 云原生6 小时前
云原生周刊:MetalBear 融资、Chaos Mesh 漏洞、Dapr 1.16 与 AI 平台新趋势
人工智能·云原生
东方佑6 小时前
docker 部署gitlib
运维·docker·容器
ZNineSun6 小时前
第一章:Go语言的起源-云原生时代的C位语言
云原生·golang
£漫步 云端彡6 小时前
docker常用命令
java·docker·eureka