目录
注:本文将基于 macOS 操作系统环境展开。
Docker入门:运维与开发
本章的初衷是在深入研究 Docker 之前,对 Docker 进行一个整体的介绍,让读者有一个全面而清晰的初步认知。本章内容主要从两种视角展开:
- 运维(Ops)视角: 关注 Docker 的基础操作和管理
- 开发(Dev)视角: 关注应用开发和容器化
在运维视角中,主要包括下载镜像、运行新的容器、登录新容器、在容器内运行命令,以及销毁容器等核心操作。
在开发视角中,主要关注与应用构建、打包和部署相关的内容。
通过上述两部分内容的了解,读者可以从整体上理解 Docker 究竟是什么,以及主要组件之间是如何相互配合的。
运维视角
Docker 架构概述
当读者安装 Docker 时,会涉及两个核心组件:
- Docker 客户端(Docker Client): 用户与 Docker 交互的命令行工具
- Docker 守护进程(Docker Daemon): 实现了 Docker 引擎的 API,负责管理镜像、容器、网络和存储卷
在不同操作系统上,客户端与守护进程的通信方式有所不同:
- Linux/macOS: 通过本地 IPC/UNIX Socket (/var/run/docker.sock) 完成通信
- Windows: 通过命名管道(Named Pipes)完成通信
读者可以使用以下命令来检查客户端和服务端是否都已经成功运行,并且可以互相通信:
docker version
期望输出应包含 Client 和 Server 两部分信息,表示通信正常。
Docker 镜像
镜像概念理解
将 Docker 镜像理解为一个包含了操作系统文件系统和应用程序的只读模板会很有帮助。如果读者有虚拟化经验,可以将其类比为虚拟机模板——虚拟机模板本质上是处于关机状态的虚拟机。在 Docker 世界中,镜像实际上等价于未运行的容器。
查看和管理镜像
在 Docker 主机上运行以下命令查看所有本地镜像:
docker image ls
在刚搭建好的 Docker 环境中,会输出类似如下的表头,但没有任何镜像:
REPOSITORY TAG IMAGE ID CREATED SIZE
拉取镜像
在 Docker 主机上获取镜像的操作被称为拉取(Pulling)。我们以 Ubuntu 为例:
# 拉取最新版本的 ubuntu 镜像,默认为 ubuntu:latest
docker pull ubuntu
# 或者拉取特定版本
docker pull ubuntu:perl
再次运行 docker image ls
命令查看刚刚拉取的镜像:
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest b60cb74dfa1b 3 weeks ago 101MB
镜像标识
Docker 的每个镜像都有自己唯一的 ID(基于 SHA256 哈希),如上述示例中的 IMAGE ID
属性对应的值 b60
即为 ubuntu 镜像源的 ID值,用户可以通过以下方式引用镜像:
- 镜像名称 + 标签: ubuntu:latest
- 镜像 ID:
b60cb74dfa1b
(通常只需要输入前几个字符即可识别,如b60
)
容器管理
启动容器
到目前为止,读者已经拥有一个拉取到本地的镜像,可以使用 docker run
命令从镜像来启动容器:
# 交互式启动容器并进入 bash shell
docker run -it ubuntu:latest /bin/bash
在上述命令中:
run
命令从镜像源nginx:latest
中启动了容器-it
参数组合了-i
(交互式)和-t
(分配伪终端),直接进入到容器内部并在后台启动/bin/bash
指定了容器启动后要执行的命令
容器内操作
在容器内,我们可以通过 ps -elf
来查看所有进程:
关键进程解释:
- 第一个进程 PID 1:
/bin/bash
进程,该进程是通过docker run
命令启动的主进程 - 第二个进程 PID 2:
ps -elf
进程,即当前正在执行的查看进程命令
容器的后台运行
如果想退出容器但保持容器在后台运行,可以通过使用组合键:
Ctrl + PQ
这会让你退回到 Docker 守护进程所在的终端,而容器继续在后台运行。
现在可以通过 docker ps
命令查看当前运行的容器:
多容器管理
有意思的是,镜像是唯一的,但我们可以同一个镜像创建多个容器实例。
# 启动第二个容器
docker run -it ubuntu:latest /bin/bash
# 使用 Ctrl + P + Q 退出
# 查看所有运行中的容器
docker ps
重新进入运行中的容器
如果想重新进入到第一个运行的容器,可以首先通过 docker ps
查看容器的相信信息,尤其关注 CONTAINER ID
以及 NAMES
两个属性的值。
可以使用 docker exec
命令:
# 方法1:使用容器ID(前几位即可)
docker exec -it d85 /bin/bash
# 方法2:使用容器名称
docker exec -it happy_mendeleev /bin/bash
docker exec
命令支持我们重新进入当前正在运行的容器。
容器生命周期管理
停止容器
# 通过 Container ID 停止容器
docker stop d85
# 通过 Container Name 停止同期
docker stop happy_mendeleev
重启容器
# 同样可以通过 ID 或者 Names 重启服务,这里只介绍通过 ID 重启
docker restart d85
删除容器
# 在停止容器运行时,注意需要区分是否已经停止运行
# 删除已停止的容器
docker rm d85
# 强制删除运行中的容器
docker rm -f d85
开发视角
容器化思维
容器即应用! 这是 Docker 的核心理念。当我们开发完成一个应用时,如何将其封装成一个可移植的"软件包"呢?在 Docker 中,这个软件包就是镜像。
示例:基于 Nginx 镜像构建简单 Web 应用
在 Docker 中,我们通过 Dockerfile
文件来定义如何构建镜像。首先我们先创建一个目录地址,用于承载我们搭建的应用。
创建 Dockerfile
# 创建项目目录
mkdir my-web-app
cd my-web-app
# 创建 Dockerfile
touch Dockerfile
vim Dockerfile
在创建好的 Dockerfile 中输入内容:
# Dockerfile
FROM nginx:alpine
# 设置工作目录
WORKDIR /usr/share/nginx/html
# 复制静态文件到容器中
COPY ./html/ .
# 暴露端口
EXPOSE 80
# 启动命令(nginx:alpine 镜像已有默认CMD)
创建静态网页文件
下面我们基于 HTML 创建一个简单的静态网页文件,首先我们先在 my-web-app
目录下创建一个名为 html
文件夹:
mkdir html
然后将下述内容粘贴到终端中。
cat > html/index.html << EOF
<!DOCTYPE html>
<html>
<head>
<title>My Docker Web App</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.container { max-width: 600px; margin: 0 auto; text-align: center; }
.success { color: #28a745; }
</style>
</head>
<body>
<div class="container">
<h1 class="success">Docker 容器化成功!</h1>
<p>这是一个运行在 Docker 容器中的静态网站。</p>
<p>当前时间:<span id="time"></span></p>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</body>
</html>
EOF
此时,我们的 my-web-app
整体架构如下:
.
Dockerfile
html
|-- index.html
通过 cat
命令查看 index.html
文件中内容,正如我们刚才粘贴创建的静态网页内容:
构建镜像
下一步,我们基于现已构建好的 Dockerfile
以及前端界面构建我们的镜像。
# 构建镜像,注意最后的 . 表示当前目录
docker build -t my-web-app:v1.0 .
构建过程输出:
当构建完成后,可以通过 docker image ls
命令查看我们构建好的镜像:
docker image ls
输出示例:
太好了,创建完成!现在我们再输入 docker image ls
命令查看所有的镜像源,就会发现多一条我们刚创建好的、名为 my-web-app
,版本为 v1.0
的镜像源:
运行应用容器
下一步,我们基于构建好的镜像文件,启动容器。
# 运行容器,将容器的80端口映射到主机的8080端口
docker run -d -p 8080:80 --name my-webapp my-web-app:v1.0
参数说明:
-d
:后台运行(detached mode)-p 8080:80
:端口映射,主机 8080 端口映射到容器 80 端口--name my-webapp
:给容器指定一个名称my-web-app:v1.0
:使用的镜像
现在,我们再通过 docker ps
命令检查,就可以发现我们已经有一个在运行的容器了~
最后,我们欣赏一下自己基于 Docker-Nginx 镜像源搭建的第一个小网络。
http://localhost:8080
完整的开发工作流
现在,让我们从宏观的工作流上总结下怎样构建一个完整的应用:
- 编写应用代码
- 创建 Dockerfile
- 构建镜像 (
docker build
) - 运行容器 (
docker run
) - 测试应用
- 推送到仓库(可选)
# 可选:推送到 Docker Hub
docker tag my-web-app:v1.0 yourusername/my-web-app:v1.0
docker push yourusername/my-web-app:v1.0
总结
通过本博文内容,我们从运维和开发两个视角了解了 Docker 的基本概念和核心操作:
运维视角重点:
- Docker 架构: 客户端-服务端模式
- 镜像管理: 拉取、查看、删除
- 容器生命周期: 创建、启动、停止、删除
- 容器操作: 进入容器、执行命令
开发视角重点:
- 容器化思维: 容器即应用
- Dockerfile: 定义镜像构建过程
- 镜像构建: 从代码到可部署的镜像
- 应用部署: 端口映射、容器命名
这些基础操作构成了 Docker 使用的核心工作流,为后续深入学习 Docker 的高级特性打下了坚实的基础。在后续博文中,我们将深入探讨 Docker 网络、存储卷、编排等高级主题。
2025.09 金融街