Docker入门 —— 在你进入容器世界之前,你需要知道什么

2021-05-31 10:53:00 浏览数 (1)

剧透:这篇文章是一个手把手的入门教程,所以准备好一杯茶和一张舒服的板凳,让我们开始创建一些容器吧。今天我们将学习Docker的基础知识,学习如何构建、运行和删除容器。

还记得那句名言吗:这能跑在我的机器上吗?相信每个开发人员都有 被环境的问题折磨得头疼的可怕经历吧?

有了Docker,现在你可以忘记这句话了。Docker允许您在本地运行将在生产环境中使用的相同(或几乎相同)的环境。

我们先理解一下Docker是什么和不是什么。

Docker是什么?

Linux容器技术很早就有了,比较有名的是Linux内核中的LXC项目。

Docker是一个基于LXC技术构建的容器引擎,使用Go语言开发,是一种执行操作系统级虚拟化(也称为“容器化”)的计算机程序。

不仅如此,Docker是一种流行的工具,可简化使用容器构建,部署和运行应用程序的过程。容器使我们可以打包应用程序需要的所有东西,例如库和其他依赖项,并将它们作为单个包打包。这样,我们的应用程序可以在任何机器上运行并且具有相同的行为。

Docker不是什么

Docker不是虚拟机(VM)。

与虚拟机不同,Docker容器不需要或包含单独的操作系统。相反,它依靠内核的功能,并对CPU和内存使用资源隔离,并使用单独的命名空间隔离应用程序对操作系统的视图。

根据上面的简短描述,下图显示了虚拟机与Docker容器之间的比较。

如我们所见,Docker容器比虚拟机更简单,使用它我们可以避免启动和维护VM的开销。由于这是一个动手教程,因此我不会深入探讨Docker的工作原理。

基本概念

镜像

Docker 的镜像概念类似于虚拟机里的镜像,是一个只读的模板,也是一个独立的文件系统,包括运行容器所需的代码和数据,用来创建新的容器。

镜像一般使用 Dockerfile 来构建, Dockerfile 是一个描述文件,里面包含若干条命令,每条命令都会在基础镜像的文件系统之上添加新的层级。

除了通过Dockerfile构建镜像,也可以直接从 DockerHub 上下载镜像别人已经创建好的镜像。

容器

Docker 容器是由 Docker 镜像创建的运行实例。Docker 容器类似虚拟机,每个容器间是相互隔离的,但隔离的效果比不上虚拟机。容器中会运行某个应用,包含应用代码及其依赖(操作系统、第三方库等)。

Docker 容器中,容器之间的隔离是通过 LinuxCGroupsNamespaces 技术来实现的。其中 CGroups 实现了对 CPU,内存,磁盘等资源访问进行限制, Namespaces 实现了命名空间上的隔离。

仓库

Docker 仓库需要托管在某个 Registry,Registry 不止一个,可以是公共的,也可以是私有的。最大的公共 Registry 是 Docker 官方提供的 Docker Hub。还可以使用 Docker 官方提供的 registry 镜像来搭建一个自己的 Registry。

仓库支持的操作类似 git,创建了新的镜像后,可以 push 推送镜像到仓库,也可以 pull 拉取镜像到本地。

动手实践

现在我们已经了解了什么是Docker,让我们开始动手实践。

安装

由于安装取决于您的操作系统,因此我们不会在本教程中介绍它。要在您的操作系统上安装Docker,请遵循官方文档

Install Docker for Mac

Install Docker for Mac

Get Docker CE for Ubuntu

这里我用的是阿里的源

代码语言:javascript复制
$ curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

另外Docker官方镜像仓库国内访问比较慢,这里也改用阿里云提供的镜像服务。首先,我们需要编辑 /etc/docker/daemon.json 文件(如果没有则新建),加入如下内容:

代码语言:javascript复制
{
  "registry-mirrors": ["https://n6syp70m.mirror.aliyuncs.com"]
}

修改之后,需要重启 docker 服务来让修改生效:

代码语言:javascript复制
$ sudo service docker restart

Hello World

正确安装并运行Docker后,让我们开始创建容器。Docker中的 HelloWorld很简单:

代码语言:javascript复制
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
9db2ca6ccae0: Pull complete
Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc
Status: Downloaded newer image for hello-world:latestHello from Docker!
This message shows that your installation appears to be working correctly.
...

如你所见,它显示以下消息:

无法在本地找到映像 hello-world:latest这意味着您在本地没有名为 hello-world的映像,因此它将自动从Docker仓库中提取。拉出 hello-world映像后,它将运行容器并显示带有来自其他信息的 HellofromDocker!消息。

恭喜,您已经在Docker中运行了"Hello World”!

创建和运行容器

既然我们已经创建了“ Hello World”示例,并且基本上了解了什么是Docker仓库,那么让我们来创建一些更复杂的东西。让我们在Python中创建一个简单的Flask应用程序。在这一点上,有一点Python和Flask的经验是最好的,但是不用担心,我们只需要知道它是Flask中的“ Hello World” Web应用程序即可。它将从容器内部在localhost上运行。首先,我们需要创建一个名为 my_web_app的目录,并将以下代码保存在名为 app.py的文件中。

代码语言:javascript复制
from flask import Flask
app = Flask(__name__)@app.route("/")
def hello():
    return "Hello World!"if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0")

这段Python代码将导入Flask软件包,创建Flask app,定义路由并在本地主机上以调试模式运行该应用程序。因此,让我们开始创建Dockerfile。为此,只需在Python文件的同一目录中创建一个名为 Dockerfile的文件,并将以下命令放入其中:

代码语言:javascript复制
# Inherit from the Python Docker image
FROM python:3.7-slim
# Install the Flask package via pip
RUN pip install flask==1.0.2
# Copy the source code to app folder
COPY ./app.py /app/
# Change the working directory
WORKDIR /app/
# Set "python" as the entry point
ENTRYPOINT ["python"]
# Set the command as the script name
CMD ["app.py"]

正如我们从注释中看到的那样,它将继承自Python Docker image,安装Flask软件包,将应用程序的源代码复制到app文件夹,将工作目录更改为 app文件夹,并设置 ENTRYPOINT和 CMD。

现在,使用 -t标志(即 tag)从构建镜像,并设置名称( flask_app)和标签( 0.1):

代码语言:javascript复制
$ docker build -t flask_app:0.1 .
$ docker images
REPOSITORY    TAG        IMAGE ID       CREATED          SIZE
flask_app     0.1        1aa01015fcfd   11 minutes ago   188MB
python        3.7-slim   84de2ffd919d   7 days ago       179MB

通过输入 docker image,我们可以看到该 Image已成功创建。然后,运行容器,指定要映射的端口(-p),并使用 -d标志(表示 detached),以免终端卡住。我们还必须将 Image的名称和标签作为参数( flask_app:0.1)传递。

打开浏览器,转到 localhost:5000地址,然后打开voilà,我们正在访问在容器内运行的Web应用程序。

停止和移除容器

由于我们的容器仍在运行,因此可以在删除之前将其停止。为此,我们只需要运行docker stop即可,将容器名称作为参数传递,例如:

代码语言:javascript复制
$ docker stop interesting_nash

我们还可以通过使用容器ID来停止容器,例如:

代码语言:javascript复制
$ docker stop 4a865da83995

如果我们现在运行 docker ps-a,我们将看到该容器处于该列表中,状态为Exited。让我们删除容器,然后删除镜像。类似于 docker stop命令,我们可以使用 docker rm命令传递容器名称或ID作为参数,例如:

代码语言:javascript复制
$ docker rm interesting_nash
# or
$ docker rm 4a865da83995

如果我们运行 docker ps-a现在我们将看到我们的容器从列表中消失了。如果我们运行“ docker images”命令,我们将在列表中看到带有标签 0.1flask_app。要删除我们的 flask_app镜像,我们可以使用 docker rmi命令,例如:

代码语言:javascript复制
$ docker rmi flask_app:0.1

如果再次运行 docker images,我们将看到 flask_app镜像已被删除。

常见命令

在本节中,你可以找到一些基本的Docker命令,例如buildrun,和exec

代码语言:javascript复制
# 构建一个Docker镜像
$ docker build -t [image_name]:[tag] .
# 运行一个指定名称的Docker容器
$ docker run --name [container_name] [image_name]:[tag]
# 提取容器的日志
$ docker logs -f [container_id_or_name]
# 在正在运行的容器中运行命令
$ docker exec -it [container_id_or_name] bash
# 显示正在运行的容器
$ docker ps
# 显示所有容器
$ docker ps -a
# 显示所有的Docker镜像
$ docker images
# 停止一个Docker容器
$ docker stop [container_id_or_name]
# 删除一个Docker容器
$ docker rm [container_id_or_name]
# 删除一个Docker镜像
$ docker rmi [image_id_or_name]

0 人点赞