Docker 入门与部署实践
1. Docker 引擎与基础操作
Docker 引擎提供了 HTTP API,可通过 UNIX 套接字(通常是
/var/run/docker.sock
)或网络进行本地访问。这意味着可以控制与 Docker 客户端或编排工具运行在不同计算机上的 Docker 引擎。
在系统上安装 Docker 后,我们可以通过以下命令运行一个可输入命令的容器:
docker run --interactive --tty ubuntu:20.04 bash
此命令会让 Docker 运行 Ubuntu 镜像,该镜像将从 Docker Hub(公共镜像的中央注册表)获取。指定
20.04
标签是为了下载代表 Ubuntu 20.04 操作系统的容器镜像。这个镜像不会包含常规 Ubuntu 安装的所有内容,但缺少的部分都可以安装。
使用
-i
参数让 Docker 以交互模式运行,
-t
参数分配一个 tty,这样就可以在容器内输入命令。默认情况下,Docker 假定要启动一个在后台运行、处理请求的容器。通过这两个选项并指定在容器内运行
bash
命令,就可以获得一个类似于 Linux 外壳的 shell。
不同的 Linux 发行版都提供基础镜像,除了 Ubuntu,还有用于运行 Python、Ruby 等环境的精简基础镜像,以及像 Alpine 这样更小的基础 Linux 镜像。镜像大小很重要,因为每次更新或在新位置运行时都需要下载。例如,Alpine 镜像大小略超过 5MB,而
ubuntu:20.04
镜像接近 73MB。可以使用以下命令比较和管理 Docker 引擎已知的镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python 3.9 a6a0779c5fb2 2 days ago 886MB
ubuntu 20.04 7e0aa2d69a15 3 weeks ago 72.7MB
alpine latest 6dbb9cc54074 4 weeks ago 5.61MB
若要删除本地的
ubuntu:20.04
镜像,可使用以下命令:
$ docker rmi ubuntu:20.04
Untagged: ubuntu:20.04
Untagged: ubuntu@sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88eb681d93
Deleted: sha256:7e0aa2d69a153215c790488ed1fcec162015e973e49962d438e18249d16fa9bd
Deleted: sha256:3dd8c8d4fd5b59d543c8f75a67cdfaab30aef5a6d99aea3fe74d8cc69d4e7bf2
Deleted: sha256:8d8dceacec7085abcab1f93ac1128765bc6cf0caac334c821e01546bd96eb741
Deleted: sha256:ccdbb80308cc5ef43b605ac28fac29c6a597f89f5a169bbedbb8dec29c987439
2. 使用 Dockerfile 构建镜像
虽然 Ubuntu 镜像可能看起来比 Python 基础镜像更好,但它不包含 Python。为了使用它,需要构建一个包含所需一切的镜像并安装自己的软件。可以使用 Dockerfile 来完成这个任务。
以下是一个基本的 Dockerfile 示例:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3
CMD ["bash"]
Dockerfile 是一个包含一组指令的文本文件。每行以大写的指令开头,后面跟着其参数。在这个示例中,有三个指令:
-
FROM
:指定要使用的基础镜像。
-
RUN
:在基础镜像安装完成后,在容器内运行命令。
-
CMD
:指定容器启动时要运行的命令。
接下来构建镜像并给它一个有用的名称,以便后续引用:
$ docker build -t ubuntu-with-python .
[+] Building 7.9s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 125B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.0s
=> [1/2] FROM docker.io/library/ubuntu:20.04 0.0s
=> [2/2] RUN apt-get update && apt-get install -y python3 7.3s
=> exporting to image 0.4s
=> => exporting layers 0.4s
=> => writing image sha256:02602f606721f36e95fbda83af09baaa9f8256e83030197e5df69fd444e5c604 0.0s
=> => naming to docker.io/library/ubuntu-with-python 0.0s
Use 'docker scan' to run Snyk tests against images to find
vulnerabilities and learn how to fix them
现在可以像之前运行 Ubuntu 镜像一样运行新镜像:
$ docker run -it ubuntu-with-python bash
root@42b83b0933f4:/# python3
Python 3.8.5 (default, Jan 27 2021, 15:41:15)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Docker 创建镜像时会创建一个包含 Dockerfile 所有指令的缓存。如果不更改文件,再次运行构建命令应该会在几秒内完成。重新排列或更改指令会从第一个更改处开始重建镜像。因此,编写 Dockerfile 时,一个好策略是对指令进行排序,将最稳定(很少更改)的指令放在顶部。
另一个建议是清理每个指令。例如,在运行
apt-get update
和
apt-get install
时,会下载大量包索引文件和
.deb
包,安装完成后就不再需要这些文件了。可以在同一个
RUN
命令中清理以减小镜像大小:
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y python3 && \
apt-get clean && \
rm -fr /var/lib/apt/lists
CMD ["bash"]
$ docker build -t cleaned-ubuntu-python .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cleaned-ubuntu-python latest 6bbca8ae76fe 3 seconds ago 112MB
ubuntu-with-python latest dd51cfc39b5a 34 minutes ago 140MB
3. Docker 镜像的共享与选择
Docker 的一个重要特性是能够与其他开发者共享、发布和重用镜像。Docker Hub 对于 Docker 容器就像 PyPI 对于 Python 包一样。
之前的例子中,Ubuntu 基础镜像就是由 Docker 从 Hub 拉取的,而且有许多现成的镜像可供使用。例如,如果想启动一个针对 Python 调整的 Linux 发行版,可以在官方 Docker Hub 网站的 Python 页面选择一个(https://hub.docker.com/_/python/)。
python:version
镜像基于 Debian,是任何 Python 项目的优秀起点。基于 Alpine Linux 的 Python 镜像也很受欢迎,因为它们生成的用于运行 Python 的镜像最小,比其他镜像小十多倍,这意味着对于想在 Docker 中运行项目的人来说,下载和设置速度会快得多。
若要使用基于 Alpine 基础镜像的 Python 3.9,可以创建如下 Dockerfile:
FROM python:3.9-alpine
CMD ["python3.9"]
构建并运行这个 Dockerfile 会进入一个 Python 3.9 的 shell。Alpine 镜像适合运行不需要大量系统级依赖或编译的 Python 应用。但需要注意的是,Alpine 有一套特定的编译工具,有时可能与某些项目不兼容。
对于基于 Quart 的微服务项目,稍大一些的基于 Debian 的 Python 镜像可能是更简单的选择,因为它有标准的编译环境和稳定性。而且,基础镜像下载后会被缓存和重用,不需要再次下载所有内容。
4. 在 Docker 中运行 Quart 应用
要在 Docker 中运行 Quart 应用,可以使用基础 Python 镜像。从这里开始,安装应用及其依赖可以通过
pip
完成,因为 Python 镜像中已经安装了
pip
。
假设项目有一个
requirements.txt
文件用于固定依赖,还有一个
setup.py
文件用于安装项目,可通过以下 Dockerfile 为项目创建镜像:
FROM python:3.9
COPY . /app/
RUN pip install -r /app/requirements.txt
RUN pip install /app/
CMD ["hypercorn", "—bind", "0.0.0.0:5000", "myservice:app"]
这里引入了
COPY
命令,它会递归地将容器外的文件和目录复制到镜像中。
EXPOSE
指令用于向运行容器的人表明这个端口应该暴露给外部世界。运行容器时,还需要使用
-p
选项连接暴露的端口。
容器内的任何进程都可以监听它想要的任何端口,并使用
localhost
进行内部通信,但容器外的任何东西都无法访问内部,除非该端口已暴露。需要注意的是,容器内的
localhost
仅指容器本身,而不是运行容器的计算机。因此,如果需要与其他服务通信,需要使用其真实的 IP 地址。
运行新容器并暴露所需端口:
$ docker run -p 5000:5000 quart_basic
[2021-05-15 15:34:56 +0000] [1] [INFO] Running on http://0.0.0.0:5000
(CTRL + C to quit)
# In another terminal:
$ curl localhost:5000
{}
停止容器可以按
Ctrl + C
,或者在另一个终端窗口中找到容器并让它停止:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
040f7f01d90b quart_basic "hypercorn —bind 0.…" 2 seconds ago Up Less than a second 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp stoic_bhabha
$ docker stop 040f7f01d90b
040f7f01d90b
COPY
命令会自动在容器内创建顶级
app
目录并将
.
中的所有内容复制进去。使用
COPY
命令时要记住,本地目录(
.
)的任何更改都会使 Docker 缓存失效,并从该步骤开始重新构建。可以创建一个
.dockerignore
文件来调整这个机制,在其中列出 Docker 应忽略的文件和目录,例如存储版本控制历史和元数据的
.git
目录。
在容器内不使用虚拟环境,因为已经处于一个隔离的环境中。还使用 Hypercorn 运行 Quart 应用,这在生产环境中是一个好做法。因此,
CMD
指令使用 Hypercorn 来指定容器启动时要运行的命令。
CMD
可以接受一个普通的 shell 命令作为参数,但这会由容器内的 shell 解释,所以如果有 shell 解释不同的符号(如
*
和
?
),可能会出错。提供一个列表会更安全,这种格式在使用 Python
subprocess
模块或
exec
系统调用时可能会熟悉。
5. Docker 部署选项
部署微服务可以通过在一个或多个实例上运行多个容器来实现。在本地开发应用时,受限于一台桌面或笔记本电脑的性能;但对于生产服务,可能会在数十或数百台服务器上运行,每台服务器运行一个提供应用不同部分的容器。在云上部署应用或扩展以满足需求的每个选项都涉及运行更多实例来运行更多容器。
以下是不同的 Docker 部署选项:
| 部署工具 | 特点 | 适用场景 |
| ---- | ---- | ---- |
| Docker Compose | 针对小规模部署,主要在单个实例中运行多个容器。 | 开发环境、暂存环境或原型。 |
| Docker Swarm | 提供不同级别的复杂度和更高的灵活性与功能。 | 需要一定规模和灵活性的部署。 |
| Kubernetes | 提供不同级别的复杂度和更高的灵活性与功能。 | 需要大规模和复杂管理的部署。 |
要尝试 Terraform、Docker Swarm 和 Kubernetes 的示例,需要在 AWS 上创建一个账户。创建账户后,访问 Identity and Access Management (IAM) 页面创建一个可以创建和更改资源的服务用户。为了安全起见,建议创建服务账户而不是使用根账户,这样任何泄露的访问密钥或秘密都可以轻松撤销并创建新的,而不会对账户访问造成重大麻烦。
在 IAM 页面,点击
Add User
并请求
Programmatic Access
以获取 API 密钥,用于在程序中使用该账户。创建一个组来更轻松地控制用户权限,授予这个新组修改 EC2 实例的权限,因为这涵盖了大部分需要更改的内容。组创建完成后,有机会下载新的
Access Key ID
和
Secret Access Key
,这些将用于授予任何创建实例和其他云资源的程序访问权限。
6. Terraform 的使用
在深入了解不同的容器编排工具之前,值得一提的是 Terraform 这个可以组织底层云实例的工具。Terraform 是 HashiCorp 公司开发的广泛采用的工具,用于将资源定义为代码。使用 Terraform 模块,可以定义云实例的设置方式、安全组、存储等一系列变量。
以下是一个描述 Amazon EC2 实例的 Terraform 配置片段:
resource "aws_instance" "swarm_cluster" {
count = 3
ami = data.aws_ami.ubuntu_focal.id
instance_type = "t3.micro" # Small for this demo.
vpc_security_group_ids = [aws_security_group.swarm_security_group.id]
key_name = "your ssh key name here"
root_block_device {
volume_type = "gp2"
volume_size = "40" # GiB
encrypted = true
}
}
这里定义了一个名为
swarm_cluster
的资源,将创建三个新实例,使用 Ubuntu Focal 基础镜像。将实例大小设置为
t3.micro
是为了测试并最小化成本。
使用 Terraform 可以在 CI/CD 管道中创建和销毁云资源,类似于测试和部署应用代码。可以使用
terraform plan
命令查看运行
terraform apply
时将对云基础设施进行的更改:
$ terraform plan
...
# module.docker-swarm.aws_instance.managers[2] will be created
+ resource "aws_instance" "managers" {
+ ami = "ami-0440ba4c79a163c0e"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
…
$ terraform apply
[terraform plan output]
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_vpc.main: Creating...
module.docker-swarm.aws_iam_policy.swarm-access-role-policy:
Creating...
module.docker-swarm.aws_sns_topic.alarms: Creating...
module.docker-swarm.aws_iam_role.ec2: Creating...
module.docker-swarm.aws_s3_bucket.terraform[0]: Creating...
module.docker-swarm.aws_sns_topic.alarms: Creation complete after 0s
[id=arn:aws:sns:eu-central-1:944409847308:swarm-vpc-alarms]
module.docker-swarm.aws_iam_policy.swarm-access-role-policy: Creation
complete after 1s [id=arn:aws:iam::944409847308:policy/swarm-vpc-swarm-
ec2-policy]
...
这个 Terraform 代码片段依赖于其他未引用的部分,如安全组资源和查找最新的 Ubuntu Focal 镜像标识符,但完整示例可在相关链接中找到。
综上所述,通过 Docker 和相关工具,可以实现微服务的高效部署和管理。根据应用的需求和规模,选择合适的部署工具和策略是关键。在实践中,还需要不断优化和调整,以确保应用的性能和稳定性。
Docker 入门与部署实践
7. 不同部署工具的详细分析
7.1 Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。它使用 YAML 文件来配置应用的服务、网络和卷等。以下是一个简单的
docker-compose.yml
文件示例:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
在这个示例中,定义了两个服务:
web
和
redis
。
web
服务使用当前目录下的 Dockerfile 构建镜像,并将容器的 5000 端口映射到主机的 5000 端口;
redis
服务使用
redis:alpine
镜像。
使用 Docker Compose 部署应用的步骤如下:
1. 创建
docker-compose.yml
文件,定义应用的服务。
2. 在终端中,进入包含
docker-compose.yml
文件的目录。
3. 运行
docker-compose up
命令来启动所有服务。
4. 若要停止服务,可使用
docker-compose down
命令。
7.2 Docker Swarm
Docker Swarm 是 Docker 内置的集群和编排工具。它允许将多个 Docker 主机组成一个集群,并在集群上运行容器。以下是使用 Docker Swarm 的基本步骤:
1. 初始化 Swarm:在一个 Docker 主机上运行
docker swarm init
命令,将该主机作为 Swarm 的管理节点。
2. 添加节点:在其他 Docker 主机上运行
docker swarm join
命令,将它们加入到 Swarm 集群中。
3. 创建服务:在管理节点上,使用
docker service create
命令创建一个新的服务。例如:
docker service create --replicas 3 --name my-web-service -p 8080:80 nginx
这个命令创建了一个名为
my-web-service
的服务,使用
nginx
镜像,启动 3 个副本,并将容器的 80 端口映射到主机的 8080 端口。
4. 管理服务:可以使用
docker service scale
命令调整服务的副本数量,使用
docker service update
命令更新服务的配置。
7.3 Kubernetes
Kubernetes 是一个开源的容器编排系统,提供了强大的自动化部署、扩展和管理容器化应用的能力。使用 Kubernetes 部署应用的基本步骤如下:
1. 安装 Kubernetes 集群:可以使用工具如
kubeadm
或云服务提供商的托管 Kubernetes 服务来创建集群。
2. 编写 Kubernetes 配置文件:使用 YAML 文件定义应用的部署、服务等资源。例如,以下是一个简单的部署配置文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app-image:latest
ports:
- containerPort: 80
-
部署应用:使用
kubectl apply -f <配置文件>命令将配置文件应用到 Kubernetes 集群中。 -
暴露服务:可以使用
kubectl expose命令将部署的应用暴露为服务,以便外部访问。
8. 云环境中的资源管理
在云环境中,使用 Terraform 可以更高效地管理资源。Terraform 通过配置文件来定义云资源,实现资源的自动化创建、修改和销毁。以下是一个使用 Terraform 管理 AWS EC2 实例的流程图:
graph TD;
A[编写 Terraform 配置文件] --> B[运行 terraform init 初始化];
B --> C[运行 terraform plan 查看变更计划];
C --> D{是否确认变更};
D -- 是 --> E[运行 terraform apply 应用变更];
D -- 否 --> C;
E --> F[资源创建完成];
F --> G[运行 terraform destroy 销毁资源];
在使用 Terraform 管理云资源时,需要注意以下几点:
- 配置文件的版本控制:将 Terraform 配置文件存储在版本控制系统中,方便团队协作和追踪变更。
- 状态文件管理:Terraform 使用状态文件来跟踪资源的状态,建议将状态文件存储在远程后端,如 AWS S3 或 HashiCorp Consul。
- 安全策略:确保配置文件中定义的资源具有适当的安全策略,如安全组规则、IAM 角色等。
9. 最佳实践总结
在使用 Docker 和相关工具进行部署时,以下是一些最佳实践:
-
镜像优化
:
- 选择合适的基础镜像,如 Alpine 镜像以减小镜像大小。
- 清理不必要的文件和依赖,避免在镜像中包含无用的数据。
- 对 Dockerfile 中的指令进行排序,将稳定的指令放在顶部,以利用 Docker 的缓存机制。
-
容器编排
:
- 根据应用的规模和需求选择合适的编排工具,如开发环境使用 Docker Compose,生产环境使用 Kubernetes。
- 合理设置容器的资源限制,避免资源过度使用或不足。
- 利用服务发现和负载均衡机制,确保应用的高可用性和性能。
-
安全管理
:
- 从可信的来源获取镜像,避免使用不可信的镜像。
- 对镜像进行数字签名,确保镜像的完整性和真实性。
- 定期更新镜像和应用,以修复安全漏洞。
10. 未来发展趋势
随着云计算和容器技术的不断发展,Docker 和相关工具也在不断演进。以下是一些可能的未来发展趋势:
-
无服务器容器
:结合无服务器计算和容器技术,实现更高效的资源利用和成本控制。
-
人工智能与机器学习集成
:在容器中运行人工智能和机器学习模型,实现更快速的模型部署和训练。
-
多集群管理
:支持跨多个云提供商和数据中心的集群管理,实现更灵活的部署和扩展。
通过不断学习和实践,掌握 Docker 和相关工具的最新技术和最佳实践,将能够更好地应对未来的挑战,实现高效、稳定和安全的应用部署。
超级会员免费看
2229

被折叠的 条评论
为什么被折叠?



