CentOS Docker 应用快速上手:从入门到实践
在当今的软件开发和部署领域,容器化技术已经成为不可或缺的一部分。而 Docker 凭借其轻量、可移植、自给自足的特性,迅速成为容器化领域的领导者。对于运行在 CentOS 系统上的服务器或开发环境来说,掌握 Docker 更是提升效率、简化部署、确保环境一致性的重要技能。
本文将带您一步步在 CentOS 系统上安装 Docker,理解其核心概念,学习如何拉取和运行容器,构建自己的镜像,并分享一些实用的技巧和常见场景。无论您是运维工程师、开发人员,还是只是对容器技术感到好奇,本文都将为您提供一份详实易懂的指南。
为什么选择 Docker?
在深入技术细节之前,我们先简单回顾一下 Docker 的核心价值:
- 环境一致性: Docker 容器包含了应用程序及其运行所需的所有依赖项(库、环境变量、配置文件等)。这意味着无论容器在哪里运行,都能保证相同的环境,从而避免了常见的“在我电脑上可以运行”的问题。
- 快速部署与扩展: 容器可以在几秒钟内启动,这极大地缩短了部署时间。当应用需要扩展时,可以轻松地启动更多容器实例。
- 隔离性: 容器之间相互隔离,每个容器都有自己的文件系统、进程空间和网络接口。一个容器的故障或安全问题不会影响到其他容器。
- 资源利用率高: 与传统的虚拟机相比,Docker 容器共享宿主机的操作系统内核,因此更加轻量,启动更快,对资源的消耗更少。
- 可移植性: 打包好的 Docker 镜像可以在任何安装了 Docker 的机器上运行,无论是开发者的笔记本电脑、测试服务器还是生产环境。
CentOS 作为一款稳定、流行的企业级 Linux 发行版,是许多服务器的首选。在 CentOS 上运行 Docker,能够充分利用其稳定性,并结合 Docker 的优势,构建出高效可靠的应用服务架构。
动手准备:安装 Docker
在 CentOS 系统上安装 Docker 既简单又直接。我们将使用 Docker 官方提供的仓库,以确保安装的是最新版本。
先决条件:
- 一台运行 CentOS 系统的服务器或虚拟机(推荐使用 CentOS 7 或 CentOS Stream 8/9)。
- 拥有
root
权限或sudo
权限的用户。 - 能够访问互联网。
安装步骤:
-
卸载旧版本(如果存在): 如果您的系统上安装过旧版本的 Docker(例如通过操作系统的默认包管理器安装),建议先将其卸载。
“`bash
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine或者对于 CentOS 8/Stream 9 使用 dnf
sudo dnf remove docker*
“`
-
安装必要的工具: 安装
yum-utils
(用于管理 yum 仓库)和一些存储驱动所需的软件包。“`bash
sudo yum install -y yum-utils device-mapper-persistent-data lvm2或者对于 CentOS 8/Stream 9 使用 dnf
sudo dnf install -y dnf-utils device-mapper-persistent-data lvm2
“`
-
添加 Docker 官方仓库: 这一步是关键,确保我们从官方源获取 Docker 的最新版本。
“`bash
sudo yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo或者对于 CentOS 8/Stream 9 使用 dnf
sudo dnf config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo
“`
-
安装 Docker Engine: 现在可以安装 Docker Community Edition (CE) 了。
“`bash
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin或者对于 CentOS 8/Stream 9 使用 dnf
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
``
y` 并回车确认即可。
如果在安装过程中提示 GPG 密钥导入,输入 -
启动 Docker 服务: 安装完成后,需要启动 Docker 服务。
bash
sudo systemctl start docker -
设置 Docker 开机自启: 让 Docker 服务在系统启动时自动运行。
bash
sudo systemctl enable docker -
验证安装: 运行一个简单的测试容器来验证 Docker 是否安装成功并正常运行。
bash
sudo docker run hello-world
如果您看到一条类似“Hello from Docker!”的消息,说明 Docker 已经成功安装并运行了第一个容器。
(可选)配置非 root 用户使用 Docker:
默认情况下,只有 root
用户或 sudo
用户才能执行 docker
命令。为了方便日常使用,可以将当前用户添加到 docker
用户组。
-
创建
docker
用户组(如果它不存在,安装时通常会创建)。bash
sudo groupadd docker -
将当前用户添加到
docker
用户组中。请将<your-user>
替换为您实际使用的用户名。bash
sudo usermod -aG docker <your-user> -
退出当前终端会话并重新登录,或者执行
newgrp docker
命令,使用户组的更改生效。之后,您就可以不使用sudo
来运行docker
命令了。bash
docker run hello-world # 再次测试,这次无需 sudo
如果在执行newgrp docker
后仍然需要 sudo,完全退出终端窗口再打开一个新的终端窗口通常能解决问题。
至此,Docker 已经在您的 CentOS 系统上安装并配置完成,可以开始探索容器的世界了。
Docker 核心概念解析
在实际操作之前,理解 Docker 的几个核心概念至关重要:
- 镜像(Image): Docker 镜像是构建容器的只读模板。它包含了应用程序及其所有依赖项、配置和运行环境。可以把镜像理解为操作系统的模板,比如一个 Ubuntu 镜像、一个 Nginx 镜像、一个 MySQL 镜像。镜像是分层的,这使得更新和分发变得高效。
- 容器(Container): 容器是镜像的运行实例。每个容器都是相互隔离的,拥有自己的文件系统、进程空间、网络接口等。您可以启动、停止、删除容器,就像管理虚拟机一样,但它更轻量。
- Dockerfile: Dockerfile 是一个文本文件,包含了一系列构建 Docker 镜像的指令。通过编写 Dockerfile,您可以定义如何组装一个镜像,包括从哪个基础镜像开始,拷贝哪些文件,安装哪些软件,运行哪些命令等。它是实现“基础设施即代码”的重要工具。
- 仓库(Registry): Docker 仓库是存放 Docker 镜像的地方。最常用的是 Docker Hub(hub.docker.com),它是一个公共的镜像仓库,您可以在这里找到大量的官方镜像和用户共享的镜像,也可以将自己构建的镜像上传到这里。此外,还可以搭建私有的 Docker 仓库。
- 数据卷(Volume): 容器的存储是临时的,容器被删除后,其中的数据也会丢失。数据卷是用于在容器和宿主机之间或容器之间共享数据,并持久化存储数据的机制。数据卷独立于容器的生命周期。
- 网络(Network): Docker 提供了多种网络模式,允许容器之间以及容器与外部世界进行通信。默认情况下,Docker 会创建一个桥接网络,使得同一宿主机上的容器可以相互通信。
理解了这些概念,我们就可以开始实际操作了。
Docker 基础操作:玩转镜像与容器
1. 搜索与拉取镜像
Docker Hub 上有海量的镜像供我们使用。
-
搜索镜像: 使用
docker search
命令可以在 Docker Hub 上搜索镜像。bash
docker search nginx
这将列出所有包含“nginx”关键词的镜像,包括官方镜像(OFFICIAL
列为[OK]
)和社区镜像。 -
拉取镜像: 使用
docker pull
命令从仓库拉取镜像到本地。如果不指定标签(tag),默认拉取最新版本(latest
)。bash
docker pull nginx # 拉取最新版本的 Nginx 镜像
docker pull ubuntu:18.04 # 拉取 Ubuntu 18.04 版本的镜像
拉取镜像时,Docker 会从仓库下载构成该镜像的所有层。由于镜像是分层的,如果本地已经存在某些层,Docker 就只会下载缺失的层,非常高效。
2. 查看本地镜像
使用 docker images
命令可以查看本地已经下载的镜像。
bash
docker images
输出会显示镜像的仓库名(REPOSITORY)、标签(TAG)、镜像 ID(IMAGE ID)、创建时间(CREATED)和大小(SIZE)。
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a210a638a613 2 weeks ago 134MB
ubuntu 18.04 a2a15febcdf3 4 months ago 64.2MB
hello-world latest d2c94e258dcb 6 months ago 13.3kB
3. 运行容器
运行容器是 Docker 最核心的功能之一,使用 docker run
命令。这是最常用的 Docker 命令,也是最复杂的,因为它有很多选项。
基本语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
-
运行第一个容器(再次): 我们之前运行过
hello-world
,它只是简单输出信息后就退出了。bash
docker run hello-world -
运行一个交互式容器: 进入一个容器内部进行操作,通常使用
-it
选项(-i
保持标准输入流开放,-t
分配一个伪终端)。bash
docker run -it ubuntu:18.04 bash
这个命令会拉取ubuntu:18.04
镜像(如果本地没有),然后在其中启动一个容器,并执行bash
命令进入容器的命令行。您现在就在一个独立的 Ubuntu 环境中了。可以尝试运行ls /
,cat /etc/os-release
等命令。输入exit
退出容器。 -
以后台模式运行容器(Daemonized): 对于 Web 服务器、数据库等服务,我们通常希望它们在后台运行,而不是阻塞当前终端。使用
-d
选项。bash
docker run -d nginx
这个命令会在后台启动一个 Nginx 容器,并返回容器的短 ID。 -
映射端口: 要从宿主机访问容器中运行的服务(例如 Web 服务器),需要将容器的端口映射到宿主机的端口。使用
-p
选项:宿主机端口:容器端口
。bash
docker run -d -p 8080:80 nginx
这个命令会在后台启动一个 Nginx 容器,并将容器内部的 80 端口映射到宿主机的 8080 端口。现在,您可以通过访问宿主机的http://<宿主机IP或域名>:8080
来访问 Nginx 提供的默认页面了。(注意:如果您的 CentOS 宿主机启用了防火墙(firewalld),可能需要开放 8080 端口:sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
和sudo firewall-cmd --reload
)。 -
为容器命名: 默认情况下,Docker 会为容器生成一个随机的名称。使用
--name
选项可以指定一个有意义的名称。bash
docker run -d --name my-nginx -p 8080:80 nginx
现在这个容器的名称就是my-nginx
,以后可以使用这个名称来管理容器(启动、停止等),而不用记忆容器 ID。 -
挂载数据卷: 为了持久化数据或在宿主机和容器之间共享数据,使用
-v
选项:宿主机路径:容器路径
。bash
mkdir /opt/my-nginx-html
echo "<h1>Hello from Docker Volume!</h1>" > /opt/my-nginx-html/index.html
docker run -d --name nginx-with-volume -p 8081:80 -v /opt/my-nginx-html:/usr/share/nginx/html nginx
这个例子将宿主机的/opt/my-nginx-html
目录挂载到容器内部 Nginx 默认的网页根目录/usr/share/nginx/html
。访问http://<宿主机IP或域名>:8081
将看到 “Hello from Docker Volume!”。宿主机路径/opt/my-nginx-html
中的内容与容器中的/usr/share/nginx/html
目录是同步的,修改宿主机文件会立即反映在容器中,反之亦然。并且,即使容器被删除,宿主机上的数据仍然保留。 -
自动清理容器: 对于一些临时性的任务容器,可以使用
--rm
选项,容器停止后会自动删除。bash
docker run --rm ubuntu:18.04 echo "This container will be removed after execution."
4. 查看运行中的容器
使用 docker ps
命令查看当前正在运行的容器。
bash
docker ps
输出会显示容器 ID(CONTAINER ID)、镜像(IMAGE)、启动命令(COMMAND)、创建时间(CREATED)、状态(STATUS)、端口映射(PORTS)和名称(NAMES)。
要查看所有容器(包括已停止的),使用 docker ps -a
。
5. 停止、启动、重启容器
可以使用容器 ID 或名称来管理容器。
-
停止容器:
bash
docker stop <容器ID或名称>
docker stop my-nginx -
启动容器:
bash
docker start <容器ID或名称>
docker start my-nginx -
重启容器:
bash
docker restart <容器ID或名称>
docker restart my-nginx
6. 进入运行中的容器
如果需要进入一个正在运行的容器内部执行命令或查看文件,可以使用 docker exec
命令。
bash
docker exec -it <容器ID或名称> bash
docker exec -it my-nginx bash
这会在 my-nginx
容器内部启动一个新的 bash 进程,并连接到该进程。这对于调试非常有用。
7. 查看容器日志
使用 docker logs
命令查看容器的标准输出和标准错误输出。
bash
docker logs <容器ID或名称>
docker logs my-nginx
要持续查看日志,可以使用 -f
选项(follow)。
bash
docker logs -f my-nginx
8. 删除容器和镜像
-
删除容器: 容器必须是停止状态才能被删除。使用
docker rm
命令。bash
docker rm <容器ID或名称>
docker rm my-nginx
如果需要强制删除一个正在运行的容器,可以使用-f
选项(不推荐,除非必要)。bash
docker rm -f my-nginx -
删除镜像: 只有在没有容器使用该镜像时才能删除。使用
docker rmi
命令。bash
docker rmi <镜像ID或名称>
docker rmi nginx
docker rmi ubuntu:18.04
如果镜像正在被容器使用,即使容器是停止状态,也无法直接删除。需要先删除使用该镜像的容器。使用-f
选项可以强制删除镜像,但这也会删除所有依赖于它的容器(不推荐)。 -
清理未使用的对象: 随着时间的推移,可能会积累许多停止的容器、未使用的网络、悬空镜像(没有标签的镜像层)和构建缓存。使用
docker system prune
命令可以清理这些对象,释放磁盘空间。bash
docker system prune
这会删除所有停止的容器、悬空的网络和悬空镜像。加上-a
选项可以清理得更彻底,包括所有未被使用的镜像(即使它们没有悬空)和构建缓存。bash
docker system prune -a
执行此命令前请务必确认,以免误删重要数据。
构建自定义镜像:Dockerfile 入门
使用现有的镜像固然方便,但在很多情况下,您需要打包自己的应用程序或定制特定的环境。这时就需要使用 Dockerfile 构建自定义镜像。
Dockerfile 是一个简单的文本文件,包含了一系列指令,Docker 读取这些指令并按顺序执行,从而构建出一个镜像。
一个简单的 Dockerfile 示例:构建一个包含静态网页的 Nginx 镜像
假设您有一个 index.html
文件,想用 Nginx 容器来提供服务。
- 创建一个目录,例如
my-nginx-app
。 - 在该目录中创建一个名为
Dockerfile
的文件(注意文件名和大小写)。 -
在该目录中创建一个名为
index.html
的文件,内容如下:html
<!DOCTYPE html>
<html>
<head>
<title>Hello Docker!</title>
</head>
<body>
<h1>My Custom Nginx Container!</h1>
<p>This page is served by Nginx running in a Docker container built from a Dockerfile.</p>
</body>
</html> -
编辑
Dockerfile
文件,内容如下:“`dockerfile
使用官方 Nginx 镜像作为基础镜像
FROM nginx:latest
将本地的 index.html 文件拷贝到容器内的 Nginx 默认网页根目录
/usr/share/nginx/html 是 Nginx 官方镜像中配置的默认网页根目录
COPY index.html /usr/share/nginx/html/
暴露容器的 80 端口(这只是一个文档说明,并不是真正的端口映射)
EXPOSE 80
容器启动时执行的默认命令(Nginx 官方镜像已经设置好了,这里只是说明)
CMD [“nginx”, “-g”, “daemon off;”]
“`
Dockerfile 常用指令解释:
FROM <image>[:<tag>]
: 指定构建镜像所基于的基础镜像。这是 Dockerfile 的第一条指令。RUN <command>
: 在镜像构建过程中执行命令。例如,安装软件包、创建目录等。每条RUN
指令都会在镜像中创建一个新的层。COPY <源路径>... <目标路径>
: 将本地文件或目录拷贝到镜像中的指定路径。源路径是相对于 Dockerfile 所在目录的路径。ADD <源路径>... <目标路径>
: 与COPY
类似,但ADD
支持解压压缩包(如.tar.gz
)和处理 URL。通常更推荐使用COPY
,因为它更透明。WORKDIR <路径>
: 设置后续RUN
、CMD
、ENTRYPOINT
等指令的工作目录。如果目录不存在,会自动创建。EXPOSE <端口> [<端口>/<协议>...]
: 声明容器在运行时监听的端口。这只是一个文档说明,并不会自动进行端口映射,端口映射需要在使用docker run
时通过-p
选项指定。ENV <key>=<value> ...
: 设置环境变量。在容器运行时可以使用这些环境变量。VOLUME <路径> [<路径>...]
: 声明一个或多个挂载点,用于将数据卷挂载到容器中。CMD <命令> [<参数>...]
或CMD ["可执行文件", "参数1", "参数2"]
: 指定容器启动时默认执行的命令。如果docker run
命令指定了其他命令,则会覆盖CMD
。一个 Dockerfile 中只能有一个CMD
指令。ENTRYPOINT <命令> [<参数>...]
或ENTRYPOINT ["可执行文件", "参数1", "参数2"]
: 指定容器启动时主要执行的命令。ENTRYPOINT
和CMD
通常一起使用,CMD
为ENTRYPOINT
提供默认参数。
构建镜像:
在包含 Dockerfile
和 index.html
文件的 my-nginx-app
目录下,打开终端,执行构建命令:
bash
docker build -t my-custom-nginx:v1 .
docker build
: 构建镜像的命令。-t my-custom-nginx:v1
: 为构建的镜像指定名称和标签(tag)。格式是名称:标签
。.
表示 Dockerfile 所在的上下文路径是当前目录。.
: Dockerfile 文件所在的目录路径。Docker Daemon 会将该目录下的所有文件(除了.dockerignore
指定的)打包发送给 Docker Daemon 进行构建。
Docker 会根据 Dockerfile 中的指令一步步执行构建过程。每条指令成功执行后,都会生成一个临时的中间层镜像,这使得构建过程可以缓存和加速。
构建完成后,使用 docker images
命令应该能看到您刚刚构建的镜像 my-custom-nginx:v1
。
运行自定义镜像构建的容器:
现在,您可以像运行其他镜像一样运行您自己的镜像了。
bash
docker run -d --name my-web-server -p 80:80 my-custom-nginx:v1
这个命令会在后台启动一个容器,使用 my-custom-nginx:v1
镜像,将容器的 80 端口映射到宿主机的 80 端口。现在访问宿主机的 IP 或域名,应该能看到您自定义的 index.html
页面。
进阶概念简述
- Docker Compose: 用于定义和运行由多个容器组成的复杂应用。通过一个 YAML 文件来配置应用的服务、网络和数据卷,然后使用一个命令就可以启动、停止、重建整个应用栈。对于微服务或需要多个相互依赖服务的应用(如 Web 应用+数据库),Docker Compose 极其方便。
- Docker Network: Docker 提供了多种网络驱动(bridge, host, overlay 等),用于连接容器。默认的桥接网络可以满足大部分单宿主机上的容器通信需求。
- Docker Volume: 除了刚才演示的绑定挂载(bind mount,直接挂载宿主机路径),Docker 还提供了 Managed Volumes。这是 Docker 管理的数据卷,数据存储在 Docker 的数据目录中,可以通过名称引用,更易于管理和备份。
常见应用场景在 CentOS 上使用 Docker
- 部署 Web 应用: 将 Nginx, Apache, Node.js, Python (Flask/Django), Java (Spring Boot) 等 Web 应用打包成镜像,在 CentOS 服务器上运行。
- 运行数据库: PostgreSQL, MySQL, MongoDB, Redis 等数据库都有官方或社区维护的 Docker 镜像,可以快速启动数据库实例用于开发、测试或轻量级生产环境。
- 搭建开发环境: 开发人员可以在本地 CentOS 或远程 CentOS 服务器上,使用 Docker 快速拉起一个与生产环境一致的开发环境,避免环境差异带来的问题。
- 持续集成/持续部署 (CI/CD): 在 Jenkins, GitLab CI 等 CI/CD 工具中,可以使用 Docker 构建和运行测试环境,打包应用成镜像,并推送到仓库,然后将镜像部署到生产环境。
- 运行各种工具: 需要运行某个特定版本的工具或软件,但不想污染宿主机环境?使用 Docker 容器是一个绝佳的选择。例如,运行某个特定版本的编译工具链、测试工具、命令行工具等。
故障排除小贴士
- 权限问题: 如果运行
docker
命令时提示权限不足,请检查用户是否在docker
用户组中,并确保已重新登录或执行newgrp docker
。 - 服务未启动: 检查 Docker 服务状态:
sudo systemctl status docker
。如果未启动,尝试启动:sudo systemctl start docker
。 -
镜像无法拉取: 检查网络连接和 DNS 设置。如果在中国大陆地区,可能需要配置 Docker Daemon 使用国内镜像加速器。编辑
/etc/docker/daemon.json
文件(如果不存在则创建),添加如下内容:json
{
"registry-mirrors": ["https://<your-mirror-url>"]
}
将<your-mirror-url>
替换为实际的镜像加速器地址(例如阿里云、腾讯云等提供的地址),然后重启 Docker 服务:sudo systemctl daemon-reload && sudo systemctl restart docker
。
* 容器无法访问外部网络或被外部访问: 检查宿主机的防火墙设置(如firewalld
),确保相关的端口已经开放。检查容器的网络模式和端口映射设置 (-p
选项)。
* 磁盘空间不足: 容器和镜像会占用磁盘空间。定期使用docker system prune -a
清理不再使用的对象。查看 Docker 占用的磁盘空间:docker system df
。
* 容器启动失败: 使用docker logs <容器ID或名称>
查看容器的启动日志,通常可以找到失败的原因。
总结与展望
通过本文的学习,您应该已经在 CentOS 系统上成功安装并运行了 Docker,理解了容器、镜像、Dockerfile 等核心概念,并掌握了运行、管理容器以及构建自定义镜像的基本操作。
Docker 极大地简化了应用的打包、分发和部署过程,提高了开发和运维效率。这仅仅是 Docker 世界的冰山一角。接下来,您可以深入学习 Docker Compose 进行多容器应用编排,了解 Docker 网络和数据卷的高级用法,探索 Docker Swarm 或 Kubernetes 等更高级的容器编排平台,以及如何将 Docker 集成到 CI/CD 工作流中。
在 CentOS 这个坚实稳定的平台上,结合 Docker 灵活强大的能力,您将能够构建和管理更加现代化、高效可靠的应用服务。
祝您在 Docker 的世界里探索愉快!