Docker入门:原理、安装与组件解析
立即解锁
发布时间: 2025-08-13 01:02:40 阅读量: 13 订阅数: 13 


使用Docker和Jenkins实现持续交付的关键实践
### Docker入门:原理、安装与组件解析
#### 1. 技术要求
在开始使用Docker之前,需要满足以下硬件和软件要求:
- 至少4GB的随机访问内存(RAM)
- 操作系统支持:macOS 10.15+、Windows 10/11 Pro 64位、Ubuntu 20.04+或其他Linux操作系统
所有示例和练习解决方案可在[此处](https://github.com/PacktPublishing/Continuous-Delivery-With-Docker-and-Jenkins-3rd-Edition/tree/main/Chapter02)找到,本章的代码实战视频可在[这里](https://bit.ly/3LJv1n6)观看。
#### 2. 什么是Docker
Docker是一个开源项目,旨在通过软件容器帮助进行应用程序部署。这种方法意味着将应用程序与其完整的运行环境(文件、代码库、工具等)一起运行。因此,类似于虚拟化,Docker允许将应用程序打包成一个可以在任何地方运行的镜像。
#### 3. 容器化与虚拟化对比
- **虚拟化**
- 在没有Docker的情况下,可以使用硬件虚拟化(通常称为虚拟机,VMs)来实现隔离和其他优势。常见的解决方案有VirtualBox、VMware和Parallels。VM模拟计算机架构并提供物理计算机的功能。如果每个应用程序都作为单独的VM镜像交付和运行,就可以实现应用程序的完全隔离。
- 虚拟化的部署方式是每个应用程序作为一个带有所有依赖项和客户操作系统的单独镜像启动,由管理程序(hypervisor)运行,模拟物理计算机架构。这种部署方法得到了许多工具(如Vagrant)的广泛支持,适用于开发和测试环境。
- 然而,虚拟化存在三个显著缺点:
- 性能低下:VM为了运行客户操作系统而模拟整个计算机架构,因此执行每个操作都有很大的开销。
- 资源消耗高:模拟需要大量资源,并且每个应用程序都需要单独进行模拟。因此,在标准桌面机器上,只能同时运行少数几个应用程序。
- 镜像体积大:每个应用程序都附带完整的操作系统,因此在服务器上部署意味着要发送和存储大量数据。
- **容器化**
- 容器化提供了不同的解决方案。每个应用程序与其依赖项一起交付,但不包含操作系统。应用程序直接与主机操作系统交互,因此没有客户操作系统的额外层。这导致了更好的性能和资源的有效利用,而且交付的Docker镜像明显更小。
- 在容器化的情况下,隔离发生在主机操作系统的进程级别。但这并不意味着容器共享它们的依赖项,每个容器都有自己正确版本的库,并且如果其中任何一个库更新,不会影响其他容器。为了实现这一点,Docker引擎为容器创建了一组Linux命名空间和控制组。因此,Docker的安全性基于Linux内核进程隔离。虽然这种解决方案已经足够成熟,但与VM提供的基于完整操作系统的隔离相比,安全性可能稍低。
#### 4. 使用Docker的必要性
- **环境问题**
- 安装和运行软件很复杂,需要考虑操作系统、资源、库、服务、权限、其他软件以及应用程序依赖的一切。而且可能存在冲突的依赖项。在一些公司,通过为不同类别的应用程序分配专用服务器来解决这些问题,例如一个用于Java 7 Web服务的服务器和另一个用于Java 8批处理作业的服务器。但这种解决方案在资源利用上不平衡,并且需要大量的IT运维团队来管理所有生产和测试服务器。
- 环境的复杂性还意味着运行应用程序通常需要专业人员。技术水平较低的人员可能难以设置MySQL、开放数据库连接(ODBC)或其他稍微复杂的工具。对于那些不是以特定操作系统二进制文件形式交付,而是需要源代码编译或其他特定环境配置的应用程序来说,情况尤其如此。
- **隔离问题**
- 保持工作空间整洁很重要,因为一个应用程序可能会改变另一个应用程序的行为。例如,应用程序共享一个文件系统,如果应用程序A将数据写入错误的目录,应用程序B可能会读取到错误的数据。它们还共享资源,如果应用程序A存在内存泄漏,不仅会使自身冻结,还可能影响应用程序B。此外,它们共享网络接口,如果应用程序A和B都使用端口8080,其中一个将会崩溃。隔离也涉及安全方面,运行有缺陷的应用程序或恶意软件可能会对其他应用程序造成损害。因此,将每个应用程序放在单独的沙箱中是更安全的做法,这样可以将可能的损害范围限制在应用程序本身。
- **应用程序组织问题**
- 服务器上常常运行着大量无人了解的应用程序,看起来十分混乱。很难检查服务器上正在运行哪些应用程序以及每个应用程序使用哪些依赖项,因为它们可能依赖于库、其他应用程序或工具。如果没有详尽的文档,我们只能查看正在运行的进程并进行猜测。Docker通过将每个应用程序作为一个单独的容器来组织,这些容器可以被列出、搜索和监控。
- **可移植性问题**
- 早期Java宣传的口号是“一次编写,到处运行”,确实Java在可移植性方面做得很好。但仍然存在一些Java无法解决的情况,例如不兼容的本地依赖项或较旧版本的Java运行时。而且并非所有软件都是用Java编写的。
- Docker将可移植性的概念提升到了一个新的高度。如果Docker版本兼容,交付的软件无论使用何种编程语言、操作系统或环境配置,都能正确运行。可以用“交付整个环境而不仅仅是代码”来概括Docker的可移植性。
- **“小猫”与“牛群”的比喻**
- 传统软件部署和基于Docker的部署之间的区别常被比喻为“小猫”和“牛群”。每个人都喜欢小猫,小猫是独特的,每只都有自己的名字,需要特殊照顾,人们对它们投入感情,它们死去时会让人伤心。相反,牛群的存在只是为了满足我们的需求,“牛群”这个词甚至是单数形式,因为它们只是一群被统一对待的动物,没有名字,没有独特性。虽然每头牛实际上是独特的(就像每台服务器一样),但这并不重要。因此,Docker背后的理念可以简单地解释为“把服务器当作牛群,而不是宠物”。
#### 5. 替代容器化技术
Docker并不是市场上唯一的容器化系统。实际上,Docker的早期版本基于开源的Linux Containers(LXC)系统,这是一个替代的容器平台。其他已知的解决方案包括Windows Server容器、OpenVZ和Linux Server。然而,Docker因其简单性、良好的市场推广和创业精神,超越了所有其他系统。它可以在大多数操作系统下运行,能让用户在不到15分钟内完成一些有用的操作,并且具有许多易于使用的功能、优秀的教程、强大的社区,可能还有IT行业中最好的标志!
#### 6. 安装Docker
- **安装前提**
- Docker社区版对不同操作系统有特定的要求:
| 操作系统 | 要求 |
| ---- | ---- |
| macOS | macOS 10.15或更高版本;至少4GB的RAM;未安装版本早于4.3.30的VirtualBox |
| Windows | 64位Windows 10/11;启用Hyper - V包;至少4GB的RAM |
| Linux | 64位架构;Linux内核3.10或更高版本 |
- 如果机器不满足这些要求,可以使用安装了Ubuntu操作系统的VirtualBox作为解决方案。虽然听起来很复杂,但考虑到在macOS和Windows中Docker引擎环境本身就是虚拟化的,这可能并不是最坏的方法。此外,Ubuntu是使用Docker支持最好的系统之一。
- **本地机器安装**
- Docker的安装过程很简单,详细说明可在其官方页面[https://docs.docker.com/get-docker/](https://docs.docker.com/get-docker/)找到。
- **Docker Desktop**
- 在本地环境中使用Docker最简单的方法是安装Docker Desktop。这样,只需几分钟,就可以设置并运行一个完整的Docker开发环境。对于Windows和macOS用户,Docker Desktop提供了一个原生应用程序,将所有设置困难隐藏在幕后。从技术上讲,Docker引擎安装在VM内部,因为Docker需要Linux内核才能运行。但作为用户,甚至不需要考虑这些,安装Docker Desktop后就可以开始使用`docker`命令。
- Docker Desktop除了提供Docker引擎外,还提供了许多额外的功能:
- 用于显示镜像、容器和卷的用户界面(UI)
- 本地Kubernetes集群
- 自动Docker更新
- 与本地文件系统集成的卷挂载
- (Windows)支持Windows容器
- (Windows)与Windows Subsystem for Linux(WSL)/WSL版本2(WSL2)集成
- 请访问[https://docs.docker.com/get-docker/](https://docs.docker.com/get-docker/)获取Docker Desktop安装指南。
- **Ubuntu安装**
- 访问[https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)可以找到在Ubuntu机器上安装Docker的指南。
- 在Ubuntu 20.04上,可以执行以下命令:
```bash
$ sudo apt-get update
$ sudo apt-get -y install ca-certificates curl gnupg lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get -y install docker-ce docker-ce-cli containerd.io
```
- 所有操作完成后,Docker应该已安装。但此时,只有`root`用户可以使用Docker命令,这意味着每个Docker命令都必须以`sudo`开头。
- 可以通过将其他用户添加到`docker`组来允许他们使用Docker:
```bash
$ sudo usermod -aG docker <username>
```
- 成功注销后,一切设置就绪。但在执行此命令时,需要注意不要将Docker权限授予不想要的用户,以免在Docker引擎环境中创建安全漏洞,这在服务器机器上安装时尤为重要。
- **其他Linux发行版安装**
- Docker支持大多数Linux发行版和架构。详细信息请查看官方页面[https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)。
- **安装测试**
- 无论选择哪种安装方式(macOS、Windows、Ubuntu、Linux或其他),安装完成后可以通过运行`docker info`命令来测试Docker是否正常工作。输出消息应类似于以下内容:
```bash
$ docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
…
```
- **服务器安装**
- 为了通过网络使用Docker,可以利用云平台提供商或手动在专用服务器上安装Docker。
- **云平台安装**:不同云平台的Docker配置不同,但在专门的教程中都有详细描述。大多数云平台允许通过用户友好的Web界面创建Docker主机,或者会说明在其服务器上执行的具体命令。
- **手动安装**:在服务器上手动安装Docker与本地安装差别不大,但需要额外的两个步骤,即设置Docker守护进程监听网络套接字和设置安全证书。
- 设置Docker守护进程监听网络套接字:默认情况下,出于安全原因,Docker通过非网络的Unix套接字运行,只允许本地通信。需要添加对所选网络接口套接字的监听,以便外部客户端可以连接。在Ubuntu中,Docker守护进程由systemd配置,因此需要修改`/lib/systemd/system/docker.service`文件中的一行:
```plaintext
ExecStart=/usr/bin/dockerd -H <server_ip>:2375
```
通过更改这一行,就可以通过指定的IP地址访问Docker守护进程。有关systemd配置的所有详细信息可以在[https://docs.docker.com/config/daemon/systemd/](https://docs.docker.com/config/daemon/systemd/)找到。
- 设置安全证书:这一步骤涉及Docker安全证书,它允许只有通过证书认证的客户端才能访问服务器。Docker证书配置的详细描述可以在[https://docs.docker.com/engine/security/protect-access/](https://docs.docker.com/engine/security/protect-access/)找到。这一步不是严格必需的,但除非Docker守护进程服务器位于防火墙后面的网络中,否则这是必不可少的。
- 如果Docker守护进程在企业网络中运行,需要配置HTTP代理,详细描述可以在[https://docs.docker.com/config/daemon/systemd/](https://docs.docker.com/config/daemon/systemd/)找到。
#### 6. 运行Docker hello - world
在控制台中输入以下命令:
```bash
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
```
这表明你已经成功运行了第一个Docker容器。下面是执行该命令时幕后发生的事情:
1. 运行Docker客户端的`run`命令。
2. Docker客户端联系Docker守护进程,请求从名为`hello-world`的镜像创建一个容器。
3. Docker守护进程检查本地是否包含`hello-world`镜像,由于没有,它从远程的Docker Hub注册表请求该镜像。
4. Docker Hub注册表包含`hello-world`镜像,因此该镜像被拉取到Docker守护进程中。
5. Docker守护进程从`hello-world`镜像创建一个新容器,并启动可执行文件以产生输出。
6. Docker守护进程将输出流式传输到Docker客户端。
7. Docker客户端将输出发送到终端。
这个过程可以用以下mermaid流程图表示:
```mermaid
graph LR
A[运行docker run hello-world命令] --> B[Docker客户端联系守护进程]
B --> C{本地是否有镜像}
C -- 否 --> D[从Docker Hub拉取镜像]
C -- 是 --> E[直接使用本地镜像]
D --> F[创建容器并运行]
E --> F
F --> G[输出结果到客户端]
G --> H[客户端显示结果]
```
#### 7. Docker组件
- **Docker客户端和服务器**
- Docker引擎由以下三个组件组成:
- 一个在后台运行的Docker守护进程(服务器)
- 一个作为命令工具运行的Docker客户端
- 一个Docker REST应用程序编程接口(API)
- 安装Docker意味着安装所有这些组件,使Docker守护进程作为服务一直在计算机上运行。在`hello-world`示例中,我们使用Docker客户端与Docker守护进程交互,但也可以使用REST API做同样的事情。而且,在`hello-world`示例中,我们连接到本地的Docker守护进程,但也可以使用相同的客户端与远程机器上运行的Docker守护进程进行交互。
- 提示:要在远程机器上运行Docker容器,可以使用`-H`选项:`docker -H <server_ip>:2375 run hello-world`。
- **Docker镜像和容器**
- **镜像**:镜像是Docker世界中的无状态构建块。可以将镜像视为运行应用程序所需的所有文件的集合,以及运行它的说明。镜像无状态,因此可以通过网络发送、存储在注册表中、命名、版本化并保存为文件。镜像采用分层结构,这意味着可以在另一个镜像的基础上构建新的镜像。
- **容器**:容器是镜像的运行实例。如果需要多个相同应用程序的实例,可以从同一个镜像创建多个容器。由于容器是有状态的,这意味着可以与它们交互并更改它们的状态。
- 例如,在一个分层结构中,最底层通常是基础镜像,大多数情况下代表一个操作系统,我们在现有的基础镜像之上构建自己的镜像。虽然技术上可以创建自己的基础镜像,但这种情况很少见。以一个例子来说,`ubuntu`基础镜像提供了Ubuntu操作系统的所有功能,`add git`镜像添加了Git工具包,然后有一个镜像添加了Java开发工具包(JDK)环境,最后,在最顶层,有一个从`add JDK`镜像创建的容器。这样的容器可以从GitHub仓库下载Java项目并将其编译为JAR文件,从而可以在不安装任何工具的情况下编译和运行Java项目。
- 分层结构是一种节省带宽和存储空间的聪明机制。例如,如果有另一个同样基于Ubuntu的应用程序,可以复用Ubuntu基础镜像的层。
通过以上内容,我们对Docker有了全面的了解,包括其原理、安装方法和主要组件。希望这些信息能帮助你更好地使用Docker进行应用程序的开发和部署。
### Docker入门:原理、安装与组件解析
#### 8. Docker镜像的构建与管理
- **Dockerfile**
- Dockerfile是用于构建Docker镜像的文本文件,它包含了一系列的指令,用于指定镜像的基础信息、安装软件、配置环境等。以下是一个简单的Dockerfile示例:
```Dockerfile
# 使用Ubuntu作为基础镜像
FROM ubuntu:20.04
# 安装必要的软件包
RUN apt-get update && apt-get install -y \
python3 \
python3-pip
# 设置工作目录
WORKDIR /app
# 复制当前目录下的所有文件到工作目录
COPY . /app
# 安装Python依赖
RUN pip3 install -r requirements.txt
# 暴露端口
EXPOSE 5000
# 定义启动命令
CMD ["python3", "app.py"]
```
- 在这个示例中,我们首先指定了基础镜像为Ubuntu 20.04,然后安装了Python 3和pip,设置了工作目录,复制了当前目录下的文件,安装了Python依赖,暴露了端口5000,并定义了启动命令。
- **构建镜像**
- 使用`docker build`命令可以根据Dockerfile构建镜像。假设上述Dockerfile文件名为`Dockerfile`,可以使用以下命令构建镜像:
```bash
$ docker build -t my-python-app:1.0 .
```
- 其中,`-t`选项用于指定镜像的标签,格式为`名称:版本`,`.`表示使用当前目录下的Dockerfile进行构建。
- **管理镜像**
- 可以使用`docker images`命令列出本地的所有镜像:
```bash
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-python-app 1.0 xxxxxxxx 5 minutes ago 200MB
```
- 使用`docker rmi`命令可以删除指定的镜像:
```bash
$ docker rmi my-python-app:1.0
```
#### 9. Docker容器的操作与管理
- **创建和启动容器**
- 前面已经介绍了使用`docker run`命令创建并启动容器,例如:
```bash
$ docker run -d -p 5000:5000 my-python-app:1.0
```
- 其中,`-d`选项表示在后台运行容器,`-p`选项用于将容器的端口映射到主机的端口,这里将容器的5000端口映射到主机的5000端口。
- **查看容器状态**
- 使用`docker ps`命令可以查看正在运行的容器:
```bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxxxxxxxxx my-python-app:1.0 "python3 app.py" 2 minutes ago Up 2 minutes 0.0.0.0:5000->5000/tcp peaceful_wozniak
```
- 使用`docker ps -a`命令可以查看所有容器,包括已停止的容器。
- **停止和启动容器**
- 使用`docker stop`命令可以停止正在运行的容器:
```bash
$ docker stop xxxxxxxxxxxx
```
- 使用`docker start`命令可以启动已停止的容器:
```bash
$ docker start xxxxxxxxxxxx
```
- **进入容器**
- 使用`docker exec`命令可以进入正在运行的容器:
```bash
$ docker exec -it xxxxxxxxxxxx /bin/bash
```
- 其中,`-it`选项表示以交互模式进入容器,`/bin/bash`表示在容器中启动一个bash shell。
#### 10. Docker网络
- **网络类型**
- Docker提供了多种网络类型,常见的有:
- **bridge**:默认的网络类型,容器通过虚拟网桥连接到主机网络。
- **host**:容器直接使用主机的网络,不进行网络隔离。
- **none**:容器没有网络连接。
- **overlay**:用于跨主机的容器网络通信。
- **创建自定义网络**
- 可以使用`docker network create`命令创建自定义网络:
```bash
$ docker network create my-network
```
- **将容器连接到网络**
- 在创建容器时,可以使用`--network`选项将容器连接到指定的网络:
```bash
$ docker run -d --network my-network my-python-app:1.0
```
#### 11. Docker数据管理
- **数据卷(Volumes)**
- 数据卷是用于持久化存储容器数据的机制。可以使用`docker volume create`命令创建数据卷:
```bash
$ docker volume create my-volume
```
- 在创建容器时,可以使用`-v`选项将数据卷挂载到容器中:
```bash
$ docker run -d -v my-volume:/app/data my-python-app:1.0
```
- 这样,容器中的`/app/data`目录就与数据卷`my-volume`关联起来,数据可以在容器重启或删除后仍然保留。
- **绑定挂载(Bind Mounts)**
- 绑定挂载是将主机上的目录或文件挂载到容器中的机制。可以使用`-v`选项进行绑定挂载:
```bash
$ docker run -d -v /host/path:/app/data my-python-app:1.0
```
- 这里将主机上的`/host/path`目录挂载到容器的`/app/data`目录。
#### 12. Docker Compose
- **简介**
- Docker Compose是一个用于定义和运行多容器Docker应用的工具。通过一个YAML文件,可以定义多个容器的配置,然后使用一个命令就可以启动、停止和管理这些容器。
- **示例YAML文件**
```yaml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/app
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: mydb
```
- 在这个示例中,定义了两个服务:`web`和`db`。`web`服务使用当前目录下的Dockerfile构建镜像,将容器的5000端口映射到主机的5000端口,挂载当前目录到容器的`/app`目录,并依赖于`db`服务。`db`服务使用MySQL 5.7镜像,并设置了数据库的根密码和数据库名。
- **使用Docker Compose**
- 使用`docker-compose up`命令可以启动所有服务:
```bash
$ docker-compose up -d
```
- 其中,`-d`选项表示在后台运行。使用`docker-compose down`命令可以停止并删除所有服务:
```bash
$ docker-compose down
```
#### 总结
通过本文,我们深入了解了Docker的各个方面,包括其原理、安装方法、组件、镜像构建与管理、容器操作与管理、网络、数据管理以及Docker Compose的使用。Docker作为一种强大的容器化技术,能够帮助我们更高效地开发、部署和管理应用程序,提高资源利用率和应用的可移植性。希望这些内容能帮助你更好地掌握Docker,在实际项目中发挥其优势。
以下是一个简单的mermaid流程图,展示使用Docker Compose部署应用的流程:
```mermaid
graph LR
A[编写docker-compose.yml文件] --> B[运行docker-compose up -d]
B --> C{服务是否正常启动}
C -- 是 --> D[应用正常运行]
C -- 否 --> E[检查配置和日志]
E --> F[修改docker-compose.yml文件]
F --> B
```
通过以上流程,我们可以使用Docker Compose快速部署和管理多容器应用。
0
0
复制全文
相关推荐










