Docker 十分钟快速入门

前言

Docker 的出现,可以说让应用环境的配置,发布和测试变得异常的轻松。

下面会介绍 Docker 的基本概念以及如何使用 docker compose 来同时管理多个容器。

一、基本概念

在学习使用 Docker 之前,我们需要知道它是用来解决什么样的问题。

比如说你写了一个 web 应用,并且本地调试没有任何问题,这时候你想发送给你的朋友试试看,或者部署到远程的云服务器上,那么首先,你需要配置相同的软件,比如数据库、web 服务器、必要的插件、库等等,而且你还不能保证软件一定能够正常的运行起来,因为别人可能用的是完全不同的操作系统,即便同样是使用 Linux,每一种发行版也会有微小的区别,为了模拟完全相同的本地开发环境,我们自然会想到使用虚拟机,但是虚拟机需要模拟硬件运行整个操作系统,不但体积臃肿内存占用高,程序的性能也会受到影响,这时候我们的 Docker 就派上了用场。

Docker 在概念上与虚拟机非常类似,但却轻量很多,它不会去模拟底层的硬件,只为每一个应用提供完全隔离的运行环境,你可以在环境中配置不同的工具软件,并且不同环境之间相互不影响,这个“环境”在 Docker 中也被称作 container/容器,讲到这里,我们就不得不提到 Docker 中三个重要概念:DockerfileImage/镜像Container/容器

  • Image/镜像:你可以把它理解成一个虚拟机的快照(Snapshot),里面包含了你要部署的应用程序以及它所关联的所有库,通过镜像,我们可以创建许多个不同的 Container 容器。

  • Container/容器:这里的容器就像是一台台运行起来的虚拟机,里面运行了你的应用程序,每一个容器是独立运行的,他们相互之间不影响。

  • Dockerfile:最后 Dockerfile 就像是一个自动化脚本,它主要被用来创建我们之前降到的镜像,这个过程就好比是我们在虚拟机中安装操作系统和软件一样,只不过是通过 Dockerfile 这个自动化脚本完成了。

二、部署程序

快速上手 Docker 的最好方法就是亲自安装并去使用它,如果你使用的是 Windows 和 Mac,你可以在官网下载一个 Docker Desktop 的应用,且在 Windows 10 上你可以使用 WSL2(也就是 Windows 下的 Linux 子系统)来运行 Docker,如果你使用的不是 Windows 最新的预览版本,WSL2 的安装可能稍微复杂一点。

在 Linux 下面我们可以直接使用包管理工具。

如果你使用的是 vscode,我也非常推荐安装 Docker 的扩展,它会提供 Dockerfile 的语法检测,代码高亮,自动补全等等,你也可以通过菜单运行各种 Docker 命令,并且在左侧面板中看到你创建的所有镜像。

接下来,我们就尝试用 Docker 来部署一个应用。

首先,我们在应用的根目录下创建一个 Dockerfile 文件。


第一行我们需要用 FROM 命令指定一个基础镜像(base image):

FROM python:3.8-slim-buster

这样可以帮我们节省许多软件安装。

可以看到在 Docker Hub 上提供了许多高质量的操作系统镜像,比如 ubuntu,debian,fedora,alpine 等等。不同的操作系统提供不同的包管理工具,比如 Ubuntu 上的 apt,Fedora 上的 dnf。当然 Docker Hub 上还有许多方便某一种语言、某种框架开发的镜像,比如 nginx,redis,node,python,tomcat 等等。由于这里我做的是 python 应用的开发,自然我会直接使用 python 的镜像,这样免去了它的安装步骤。

FROM python:3.8-slim-buster:这里的 python 是官方镜像的名字,冒号后面这一串是版本号,同时也是一个标签(Tag),我们可以点击 python 转到 Docker Hub 的镜像页面,里面可以找到所有支持的标签,比如我们这里用的是 python 3.8 版本,运行在 debian buster 的发行版上。


后面的 WORKDIR 指定了所有 Docker 命令的工作路径(working directory):

WORKDIR /app

注意是这个命令之后的所有 Docker 命令,比如我们马上要讲到的 RUN、COPY 等等。如果这个路径不存在,Docker 会自动帮你创建。这样可以避免使用绝对路径或者手动 cd 切换路径,增加程序的可读性。


之后,我们可以调用 COPY 命令将所有的程序拷贝到 Docker 镜像中:

COPY . .

COPY <本地路径> <目标路径>:第一个参数代表本地文件,. 代表程序根目录下的所有文件。第二个参数代表 Docker 镜像中的路径,这里的 . 代表当前的工作路径,也就是之前指定的 app 目录。


随后的 RUN 允许我们在创建镜像时运行任意的 shell 命令:

RUN pip3 install -r requirements.txt

因为我们使用的是 Linux 镜像,所以像 echo、pwd、cp、rm 这些都是合法的。比如这里我用到 pip install 来安装 python 程序的所有关联。

通过以上的所有命令,我们就可以完成一个 Docker 镜像的创建。


在 Dockerfile 的最后,我们会用到 CMD 来指定当 Docker 容器运行起来以后要执行的命令:

CMD ["python3", "app.py"]

CMD ["可执行文件", "参数1", "参数2"...]

大家需要注意这里容器和镜像的区别,容器 ≠ 镜像。并且它和之前讲到的 RUN 不一样,RUN 是创建镜像的时候使用的,而 CMD 是运行容器的时候使用的。

到这里,我们的自动化脚本 Dockerfile 就完成了。

三、镜像创建、启动、停止、删除

接下来我们可以使用 docker build 来创建一个镜像:

docker build -t image-name .

-t : tag/标签:这里的 -t 指定了我们镜像的名字。

最后面的 . 告诉 docker 应该在当前目录下寻找这个 Dockerfile,这个不能省略。

第一次调用 docker build 会比较慢,因为 Docker 会下载必要的镜像文件,然后一行行运行我们的指令,不过再次调用就会快很多,因为 Docker 会缓存之前的每一个操作,这个在 Docker 中也被称作分层(Layers),这里我们就不展开讨论了。


有了镜像 以后,我们可以通过 docker run 来启动一个容器:

docker run -p 80:5000 -d image-name

这里需要注意的是这个 -p 参数,它会将容器上的某一个端口映射到你的本地主机上,这样你才能从主机上访问容器中的 Web 应用,前面的 80 是我们本地主机上的端口,后面是容器上的端口,这个不要搞反了。

第二个参数 -d (--detached)让容器在后台运行,这样容器的输出不会直接显示在控制台,如果不出意外的话,你已经可以在浏览器中访问这个 Web 应用了。


我们通过 Docker Desktop 这个图形界面,可以查看应用在后台的所有输出,这个对于调试非常方便,同时我们可以看到当前容器的各种信息,这里的 Containers 中显示了我们创建的所有容器,我们可以选择停止、重启或者删除它们,还可以通过 Shell 远程调试这个容器,下面是它们所对应的命令行指令:

操作命令行指令
列举所有的容器docker ps
停止容器docker stop <容器 ID>
重启容器docker restart <容器 ID>
删除容器docker rm <容器 ID>
启动一个远程 Shelldocker exec -it <容器 ID> /bin/bash

需要注意的是,当我们删除一个容器的时候,之前所作的修改,新添加的数据会全部丢失,这就好比是我们删除一个虚拟机,里面的数据会一同销毁一样,如果我们希望保留容器中的数据,我们可以使用 Docker 提供的 volume 数据卷。

Volume/数据卷:你可以把它当作是一个在本地主机和不同容器中共享的文件夹,比如你在某个容器中修改了某一个 volume 的数据,它会同时反映在其他的容器上,我们可以通过 docker volume create 来创建一个数据卷:

docker volume create image-name-data

随后在启动容器的时候,我们可以通过 -v 参数指定将这个数据卷挂载(mount)到容器中的哪一个路径上:

docker run -dp 80:5000 -v image-name-data:/etc/project image-name

这里可以看到我们将 image-name-data 挂载到了 /etc/project 这个路径下,向这个路径写入的任何数据都会被永久保存到这个数据卷中。

四、docker compose 管理多个容器

之前我们讲到的例子都只涉及单个容器,但在实际使用中,我们的应用程序可能会用到多个容器共同协作,比如我们可以使用一个容器来运行 Web 应用,另一个容器来运行数据库系统,这样可以做到数据和应用逻辑的有效分离,比如当 Web 程序宕机了,数据库依然在有效运转,这时我们只需要修复 Web 容器即可。

而 docker compose 刚好可以帮我们做到这一点,我们可以创建一个 docker-compose.yml 文件,在这个文件下,我们通过 services 来定义多个 container:

version: "3"
​
services:
  web:
    build:
    ports:
      - "80:5000"
  db:
    image: "mysql"
    environment:
      MYSQL_DATABASE: db
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - image-name-data:/var/lib/mysql
  
  volumes:
    image-name-data:

比如这里我们定义一个 web 容器,它里面运行了我们的 web 应用。

然后再定义一个 db 容器,里面运行了 mysql 数据库系统。这里我们可以通过这两个环境变量指定数据库的名字和连接密码。同时在 db 容器中,我们还可以通过 volumes 指定一个数据卷用来永久存放数据。

定义完毕之后,我们保存文件,使用 docker compose up 来运行所有的容器:

docker compose up -d

这里的 -d(detach)同样代表在后台运行所有的容器,不直接输出到控制台。

与这个命令对应的,我们可以使用 docker compose down . 来停止并删除所有的容器:

docker compose down

不过新创建的数据卷需要我们手动删除,除非我们在后面加入 --volumes 参数:

docker compose down --volumes

另外刚刚讲到的所有操作也都可以在图形界面中完成。

总结

到这里呢,我们就讲完了 Docker 的基本概念,关于 Dockerfile、compose 的更多使用细节,还是建议大家去参看官方的文档,另外 Docker 的中文教程,我觉得也十分不错,Docker —— 从入门到实践

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值