Docker 入门指南:告别部署噩梦!

Docker 入门指南:告别部署噩梦!

入门级开发者常常面临代码更新、发布和部署效率低下,以及环境一致性难以维护等痛点。在开发环境中运行顺畅的代码,换一台机器就可能报错。在云计算时代,使用传统方式部署代码显得过时。本文将向您介绍 Docker。

Docker 基于 Go 语言,遵循 Apache 2.0 开源协议,是一种应用容器引擎。这种容器化技术让开发者能够将应用程序及其依赖打包成轻量级、可移植的容器。这些容器可以在任何流行的 Linux 机器上部署,无需担心环境差异。

Docker 与虚拟机(VM)

如上所述,Docker 利用了虚拟化技术。谈到虚拟化,就不得不提虚拟机(VM)。由于两者都依赖虚拟化,自然会让人好奇它们之间的区别。我们来深入探讨一下。

首先,看一个典型的 VM 架构图。在基础设施(代表底层硬件)之上,有一个 hypervisor(虚拟机监视器)。它作为物理服务器和操作系统之间的中介,允许多个操作系统和应用程序共享底层硬件。虚拟机在宿主机操作系统之上运行多个不同的操作系统,并利用 hypervisor 访问底层硬件。

如果你需要运行三个隔离的应用程序,就需要创建三个虚拟机。这意味着 hypervisor 之上要运行三个操作系统,导致巨大的资源开销。

典型的 VM 架构图

(注:图中应在 Hypervisor 上方显示 Host Operating System)

相比之下,Docker 非常轻量。它的守护进程(Docker Daemon)取代了 hypervisor,直接运行在操作系统之上。应用程序的源代码和依赖被打包成 Docker 镜像。然后 Docker 引擎用这个镜像创建容器。不同的应用程序在隔离的容器中运行。

此外,Docker 守护进程直接与操作系统通信,为 Docker 容器分配资源。由于没有完整操作系统的开销,容器启动时间从虚拟机的几分钟缩短到 Docker 容器的毫秒级,大大提高了效率,并节省了大量磁盘空间和其他系统资源。

尽管 Docker 优势明显,但它并不能完全取代虚拟机。每种技术各有千秋。虚拟机擅长隔离整个运行时环境,云提供商通常通过虚拟机来隔离用户。而 Docker 通常隔离不同的应用程序。

如何使用 Docker

Docker 安装(以 CentOS 7 为例)

  1. 安装必要的系统工具:
yum install -y yum-utils device-mapper-persistent-data lvm2 
  1. 更新系统内核和 yum 缓存:
yum update
yum makecache fast
  1. 安装 Docker 并启动:
yum -y install docker-ce
systemctl start docker 
  1. 测试 Docker 是否安装成功:
docker run hello-world 

如果屏幕上显示 “Hello from Docker”,恭喜你!安装完成。

概念

在深入学习 Docker 之前,先了解几个关键概念,以便更顺畅地学习。

  1. Docker 镜像:Docker 镜像是用于创建 Docker 容器的模板
  2. Docker 容器:Docker 通过镜像创建容器,用于运行一组独立的应用程序
  3. Docker 仓库:用于保存镜像的代码仓库

通常,我们从 Docker 仓库下载合适的镜像,然后用它创建容器来运行我们的应用程序。

示例

通过两个常见示例来连接这些概念,说明如何使用 Docker。

使用 Docker 安装 Python

如前所述,使用 Docker 容器的第一步是从仓库下载对应的镜像。这就引出了本教程的第一个命令:

  • 用途: 在镜像仓库中搜索特定镜像。
  • 语法: docker search [OPTIONS] TERM
  • 示例: docker search python
  • 说明: 在仓库中搜索与 Python 相关的镜像。
[root@novita ~]# docker search python
INDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/python                           Python is an interpreted, interactive, obj...   4356      [OK]
docker.io   docker.io/django                           Django is a free web application framework...   856       [OK]
docker.io   docker.io/pypy                             PyPy is a fast, compliant alternative impl...   196       [OK]
docker.io   docker.io/kaggle/python                    Docker image for Python scripts run on Kaggle   125                  [OK]
docker.io   docker.io/arm32v7/python                   Python is an interpreted, interactive, obj...   38
docker.io   docker.io/centos/python-35-centos7         Platform for building and running Python 3...   36

我们选择官方镜像,标签(版本)为 3.7。

docker pull

  • 用途: 从镜像仓库拉取或更新指定镜像。
  • 语法: docker pull [OPTIONS] NAME:TAG
  • 示例: docker pull python:3.7
  • 说明: 从仓库下载标签为 3.7 的 Python 镜像。
[root@novita ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============>                                     ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================>      ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==>                                                ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7

Docker 现已下载指定镜像。查看现有的 Docker 镜像:

docker images

  • 用途: 列出本地镜像。
  • 语法: docker images [OPTIONS] [REPOSITORY[:TAG]]
  • 示例: docker images
  • 说明: 查看所有本地 Docker 镜像。
[root@novita ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/python        3.7                 42d620af35be        6 days ago          918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        7 days ago          179 MB
docker.io/golang        latest              f50db16df5da        9 days ago          774 MB

python3.7 镜像已存在。我们用该镜像创建一个容器。

docker run

创建容器之前,简单提一下 ID。在 Docker 中,ID 唯一标识镜像或容器。我们通过 “命令 + ID” 来交互。例如,前面代码中 python3.7 的镜像 ID 是 42d620af35be。

  • 用途: 创建一个新容器。
  • 语法: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

为了测试 Python 环境,我们在本地创建一个 hello.py 文件:

#!/usr/bin/python 
import sys 

print("Hello, Docker!") 
print(sys.version)  # Output the Python version number 

假设这段代码保存在 /root/code/python 下:

[root@novita python]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python hello.py 
Hello, Docker! 
3.7.4 (default, Jul 13 2019, 14:04:11) [GCC 8.3.0] 

我们来分解一下这个命令:

  • docker run:创建容器。
  • -v $PWD:/usr/src/code:将本地目录挂载到 Docker 容器中。这里将执行命令所在的目录挂载到容器内的 /usr/src/code。冒号分隔本地路径和容器路径。可以使用绝对路径代替 $PWD
  • -w /usr/src/code:设置容器的工作目录。由于 Python 代码目录被挂载到 /usr/src/code,我们将其设为工作目录。
  • python:3.7:指定镜像。也可以使用镜像 ID。
  • python hello.py:在容器中执行此命令。

思考题: 如果 /root/data/ 下有一个 hello.go 文件,你想使用镜像 ID 为 f50db16df5da 的 Golang 容器运行它,命令应该是什么?(提示:运行 Go 代码的命令是 go run FILENAME

使用 Docker 安装 MariaDB

假设你现在可以搜索并下载 MariaDB 镜像,我们来重点讨论如何启动它。

像数据库这样的服务需要在宿主机上开放相应端口。如何用 Docker 实现这一点?我们使用端口映射,类似于挂载目录。

[root@novita python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456  --restart unless-stopped 3a2ef06682ac 
  • -d:后台运行容器。
  • -p 3306:3306:将容器内的 3306 端口映射到宿主机的 3306 端口。
  • -e MYSQL_ROOT_PASSWORD=123456:将 MariaDB 的 root 密码设置为 123456。
  • --restart unless-stopped:如果容器意外停止,自动重启。
  • 3a2ef06682ac:用于创建容器的镜像 ID。

现在,验证数据库服务是否正在运行:

docker ps

  • 用途: 列出容器。
  • 语法: docker ps [OPTIONS]
[root@novita ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
107b52416c13        3a2ef06682ac        "docker-entrypoint..."   5 minutes ago       Up 5 minutes        0.0.0.0:3306->3306/tcp                                                                       quizzical_mcnulty 

接下来,进入容器的内部环境。

docker exec

  • 用途: 在运行中的容器中执行命令。
  • 语法: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
  • 示例: docker exec -it 107b52416c13 bash
  • 说明: 访问 ID 为 107b52416c13 的容器并执行 bash 命令。

进入容器后,可以像在普通 Linux 环境中一样交互。使用之前设置的凭据即可访问 MariaDB。

[root@novita ~]# docker exec -it 107b52416c13 bash 
root@107b52416c13:/# mysql -u root -p123456 
Welcome to the MariaDB monitor.  Commands end with ; or \g. 
Your MariaDB connection id is 11 
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
MariaDB [(none)]> 

到目前为止,你已经学到了 Docker 的基础知识。试着探索更多内容。

Novita AI 是一个一站式云平台,助力您的 AI 雄心。通过无缝集成的 API、无服务器计算和 GPU 加速,我们提供成本效益高的工具,助您快速构建和扩展 AI 驱动的业务。消除基础设施烦恼,免费开始使用 —— Novita AI 让您的 AI 梦想成为现实。