Docker 入门必读:深度解析 docker run 与 docker start 的本质区别

作为一名开发者,你是否曾在容器化技术的世界里感到迷茫?尤其是当我们面对 Docker 那些看似相似的命令时,往往容易混淆。在这篇文章中,我们将深入探讨两个极易混淆但又至关重要的指令:INLINECODE599bc2fcINLINECODE72001908。理解它们之间的区别,不仅能帮助你更高效地管理容器,还能让你在面对生产环境问题时更加游刃有余。我们将一起探索它们的工作原理、适用场景,并通过大量的实战代码示例,彻底掌握这两个核心命令。

Docker 核心概念回顾

在深入命令之前,让我们先快速回顾一下 Docker 的核心概念,确保我们在同一频道上。

Docker 是一种基于操作系统级虚拟化的开源平台,它允许我们将应用及其依赖环境打包成一个轻量级、可移植的镜像。这不仅解决了经典的“在我的机器上能跑,为什么在服务器上不行”的问题,还极大地简化了从开发到部署的流程。

在这个过程中,我们会频繁接触到以下三个术语:

  • 镜像: 可以把镜像看作是一个“只读”的模板,就像是面向对象编程中的“类”。它包含了运行应用程序所需的所有内容——代码、运行时、库、环境变量和配置文件。常见的镜像如 INLINECODEdbf35e97、INLINECODE7bfc8611 或 python
  • 容器: 容器是镜像运行时的实体。如果镜像是“类”,那么容器就是“实例”。它是相互隔离的,拥有自己的文件系统,彼此之间互不影响。我们可以启动、停止、删除容器,而不会影响底层的镜像。
  • Dockerfile: 这是一个文本文档,其中包含了构建 Docker 镜像所需的所有指令。通过 docker build 命令,我们可以自动地读取 Dockerfile 并创建镜像。

docker run:从无到有的创造者

当我们谈论部署一个新应用时,INLINECODE14b05c15 是我们最常用的命令。简而言之,INLINECODE792ba04d 的作用是创建并启动一个新容器。

它的底层逻辑非常清晰,我们可以将其拆解为以下四个步骤:

  • 检查镜像: Docker 首先检查本地是否已经存在指定的镜像。如果不存在,它会自动从 Docker Hub(或其他配置的注册表)拉取最新的镜像。
  • 创建容器: 利用该镜像,Docker 在文件系统上创建一个新的可写层。
  • 分配资源: 为容器分配 CPU、内存、网络端口以及存储卷等资源。
  • 启动执行: 启动容器,并执行镜像定义的默认命令,或者我们在命令行中指定的自定义命令。

#### 实战代码示例 1:运行一个简单的 Nginx 容器

让我们尝试运行一个最经典的 Nginx 服务器。打开你的终端,输入以下命令:

docker run -d -p 8080:80 --name my-web-server nginx

命令详解:

  • docker run: 告诉 Docker 我们要运行一个新容器。
  • INLINECODE9e0b5038: 这是 INLINECODE4ca2c575 的缩写,表示“后台运行”。这样容器不会占用我们的终端窗口,而是在后台静默运行。
  • INLINECODEd0e2cf7c: 这是端口映射。冒号左边是宿主机端口,右边是容器端口。这意味着我们可以通过访问本地机器的 INLINECODE1f8afba6 端口来访问容器内部的 80 端口。
  • INLINECODEb400179b: 给这个容器起个名字,方便日后管理。如果不加这个,Docker 会随机生成一个名字(比如 INLINECODE69c8b44b)。
  • nginx: 这是我们使用的镜像名称。

运行后,你可以在浏览器访问 INLINECODE57e886e6,看到 Nginx 的欢迎页面。此时,如果你运行 INLINECODE0dc5d250,你会看到 my-web-server 正在运行。

#### 实战代码示例 2:运行并进入交互式终端

有时候,我们需要进入容器内部进行调试。比如,我们要启动一个 Ubuntu 容器并在里面执行命令:

docker run -it ubuntu bash

命令详解:

  • -i: 交互式操作,保持 STDIN 打开。
  • -t: 分配一个伪终端。
  • ubuntu: 使用的镜像。
  • bash: 容器启动后要执行的命令。这里我们启动了一个 Bash Shell。

执行后,你的终端提示符会变成类似 INLINECODE7cb9a2ad 的形式。现在你就在容器内部了!你可以尝试 INLINECODE66596cad 或 INLINECODE60a28a62。输入 INLINECODE795a202b 可以退出,同时容器也会随之停止。

docker start:唤醒沉睡的容器

理解了 INLINECODEced37840,INLINECODEe5a6c7f5 就非常简单了。这个指令仅仅用于启动一个已经存在但处于停止状态的容器。它不会创建新容器,也不会拉取新镜像。它就像是按下了电脑的电源键,唤醒休眠的系统。

#### docker start 的核心逻辑

  • 寻找容器: Docker 根据提供的容器 ID 或名称在本地查找。
  • 检查状态: 只有状态为“已停止”的容器才能被 start。如果容器已经在运行,该命令会报错或提示无操作。
  • 保持原配置: 容器会使用之前创建时定义的配置(如端口映射、环境变量等)启动。这意味着你无法在 INLINECODEf39225da 时临时添加新的端口映射,那是 INLINECODEce403cb1 的事。

#### 实战代码示例 3:停止与重启

让我们延续之前的 my-web-server 例子。

首先,停止它:

docker stop my-web-server

此时,运行 INLINECODE7efaa24b,你会发现它不见了。但它还在,只是睡着了。运行 INLINECODEf02588c1,你依然能看到它,状态变成了 Exited

现在,让我们用 docker start 唤醒它:

docker start my-web-server

你会看到容器 ID 被打印出来。再次访问 INLINECODEa876106f,你会发现它又复活了!而且,之前的端口映射 INLINECODEe969e7ce 依然有效,因为这些设置是保存在容器配置中的。

深度对比:INLINECODEf1007f06 vs INLINECODEbcf4ff97

为了让你一目了然,我们整理了以下对比表格:

特性

INLINECODE1b9598e4

INLINECODEfcda6479 :—

:—

:— 核心动作

创建新容器 + 启动

启动已有的旧容器 镜像依赖

必须指定镜像名称(如 nginx

不需要镜像,只需容器名称或 ID 数据持久化

每次运行都会生成一个新的容器实例

复用同一个容器实例,保留内部状态(除非加了 --rm配置灵活性

极高,可以每次指定不同的端口、环境变量、挂载目录

低,严格遵循创建时的初始配置 典型场景

首次部署、测试新镜像、一次性执行任务

重启服务、恢复维护后的服务

进阶实战:构建并运行自定义 Python 应用

光说不练假把式。让我们通过构建一个简单的 Flask Web 应用来综合运用这些知识。我们将亲手编写代码、构建镜像,并使用 INLINECODE7c3cfbe5 部署它,然后体验 INLINECODE25e019b0 的过程。

#### 1. 准备项目目录

在你的电脑上创建一个新文件夹,比如叫 flask_demo,并进入该目录。

#### 2. 创建应用代码

创建一个名为 app.py 的文件,写入以下代码:

# 引入 Flask 库
from flask import Flask
# 初始化应用
app = Flask(__name__)

# 定义路由
@app.route(‘/‘)
def home():
    return "

欢迎来到 Docker 实战课堂!

这是 docker run vs docker start 的演示。

" if __name__ == ‘__main__‘: # 启动服务,监听所有 IP 的 5000 端口 app.run(host=‘0.0.0.0‘, port=5000)

#### 3. 编写依赖文件

我们需要告诉 Docker 需要安装哪些 Python 库。创建 requirements.txt

flask==2.3.0

#### 4. 编写 Dockerfile

这是构建镜像的蓝图。创建 Dockerfile(注意没有后缀名):

# 使用官方 Python 运行时作为父镜像
FROM python:3.9-slim

# 设置容器内的工作目录
WORKDIR /app

# 将依赖文件从宿主机复制到容器的 /app 目录
COPY requirements.txt .

# 安装 requirements.txt 中定义的依赖
RUN pip install --no-cache-dir -r requirements.txt

# 将当前目录下的所有文件复制到容器的 /app 目录
COPY . .

# 声明容器对外提供服务的端口
EXPOSE 5000

# 定义容器启动时执行的命令
CMD ["python", "app.py"]

#### 5. 构建镜像

打开终端,确保在 flask_demo 目录下,运行:

docker build -t my-flask-app:v1 .

这里的 INLINECODE8d13a429 给镜像打了个标签。注意最后的 INLINECODEaff28933,它表示使用当前目录作为上下文。

#### 6. 首次运行

镜像构建成功后,我们使用 docker run 来启动它:

docker run -d -p 5000:5000 --name my-flask-container my-flask-app:v1

现在访问 http://localhost:5000,你应该能看到我们的欢迎页面。

#### 7. 体验 docker start

假设我们想暂停服务器维护一下:

docker stop my-flask-container

网页无法访问了。维护完成,现在我们不需要重新构建,也不需要 run,直接唤醒它:

docker start my-flask-container

看,服务瞬间恢复,且内部数据(如果有)都不会丢失。

最佳实践与常见陷阱

在日常开发中,我们总结了一些实用的经验和避坑指南,希望能帮助你少走弯路。

#### 1. 警惕“僵尸容器”

如果你频繁使用 INLINECODE8832c705 而不加 INLINECODE66e87f75 参数(退出自动删除),你的后台会堆积大量已停止的容器。

问题: 每次运行 INLINECODE86f8acba,即使名字相同,只要旧的没删,Docker 可能会因为名字冲突报错,或者创建了一堆名字类似 INLINECODEb88de3c2, my-web-server2 的容器。
解决方案:

  • 对于测试,使用 --rm
  •     docker run --rm -p 8080:80 nginx
        

当你 Ctrl+C 停止它时,容器会被自动删除,保持环境整洁。

  • 定期清理:使用 docker container prune 命令删除所有已停止的容器。

#### 2. 不要试图用 docker start 修改配置

这是新手常犯的错误。

错误场景: 你发现容器的 8080 端口被占用了,想用 docker start my-container -p 8081:80 换个端口重启。
结果: 这会报错。docker start 不接受运行时参数修改。
正确做法: 你只能删掉旧容器(INLINECODE0150b199),然后用 INLINECODE4384f1dd 重新创建一个指定新端口的容器。为了避免丢失数据,这就是为什么数据卷挂载在生产环境中如此重要的原因。

#### 3. 查看日志的重要性

当容器使用 docker start 启动失败,或者在后台莫名退出时,不要瞎猜。

实用技巧:

使用 docker logs 查看应用的标准输出。这是排查启动失败(比如代码报错、配置文件路径错误)最快的方法。

docker logs my-flask-container

总结

在这篇文章中,我们一起深入探讨了 Docker 的两个基石命令。让我们最后回顾一下关键点:

  • INLINECODE30b0f7cc = INLINECODE03c897f3 + docker start:它是“从零开始”的指令,用于初始化全新的环境。当你需要部署新服务或修改配置参数时,请使用它。
  • docker start:它是“唤醒”的指令,用于重启现有的服务。当你只是想暂停一下服务(比如停止数据库省电)后再恢复,或者服务崩溃后重启,请使用它。

掌握这两个命令的区别,是你从 Docker 小白迈向高手的必经之路。希望这篇详尽的文章能让你在终端前敲击命令时更加自信。如果你在实际操作中遇到了问题,不妨多看看 INLINECODEbe16c5f3 和 INLINECODEa6965aa3,答案往往就藏在那里。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/37520.html
点赞
0.00 平均评分 (0% 分数) - 0