完成Docker安装后,运行以下命令测试Docker安装:
$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.
...
你好,世界
玩Busybox
现在我们已经完成了所有设置,现在是时候弄清楚了。在本节中,我们将在我们的系统上运行Busybox容器并尝试使用该docker run
命令。
首先,让我们在终端中运行以下命令:
$ docker pull busybox
注意:根据您在系统上安装docker的方式,
permission denied
运行上述命令后可能会看到错误。如果您使用的是Mac,请确保Docker引擎正在运行。如果您使用的是Linux,请在docker
命令前添加前缀sudo
。或者,您可以创建一个docker组来解决此问题。
该pull
命令从Docker注册表中获取busybox 映像并将其保存到我们的系统中。您可以使用该命令查看系统上所有图像的列表。docker images
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
Docker Run
大!现在让我们根据这个图像运行一个Docker 容器。为此,我们将使用全能docker run
命令。
$ docker run busybox
$
等等,什么都没发生!那是一个错误吗?好吧,不。在幕后,发生了很多事情。当您调用时run
,Docker客户端会找到映像(在本例中为busybox),加载容器,然后在该容器中运行命令。当我们运行时docker run busybox
,我们没有提供命令,所以容器启动,运行一个空命令然后退出。嗯,是的 - 有点无聊。让我们尝试一些更令人兴奋的事情。
$ docker run busybox echo "hello from busybox"
hello from busybox
很好 - 最后我们看到一些输出。在这种情况下,Docker客户端尽职尽责地echo
在我们的busybox容器中运行该命令,然后退出它。如果你注意到,所有这一切都很快发生。想象一下,启动虚拟机,运行命令然后杀死它。现在你知道为什么他们说集装箱很快!好的,现在是时候看到docker ps
命令了。该docker ps
命令显示当前正在运行的所有容器。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
由于没有容器在运行,我们看到一个空行。让我们尝试一个更有用的变体:docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
14e5bd11d164 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago thirsty_euclid
所以我们上面看到的是我们运行的所有容器的列表。请注意,该STATUS
列显示这些容器在几分钟前退出。
您可能想知道是否有一种方法可以在容器中运行多个命令。我们现在试试吧:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
run
使用-it
标志运行命令会将我们附加到容器中的交互式tty。现在我们可以根据需要在容器中运行尽可能多的命令。花一些时间来运行你最喜欢的命令。
危险区域:如果您感觉特别喜欢冒险,可以试试
rm -rf bin
容器。确保在容器中运行此命令,而不是在笔记本电脑/台式机中运行。这样做不会让像任何其他命令ls
,uptime
工作。一旦一切都停止工作,您可以退出容器(键入exit
并按Enter键),然后使用该docker run -it busybox sh
命令再次启动它。由于Docker每次都创建一个新容器,所以一切都应该重新开始。
这结束了对强大docker run
命令的旋风之旅,这很可能是你最经常使用的命令。花一些时间来适应它是有道理的。要了解更多信息run
,请使用docker run --help
查看它支持的所有标志的列表。随着我们的进一步发展,我们将看到更多的变种docker run
。
在我们继续前进之前,让我们快速谈谈删除容器。我们在上面看到,即使我们已经退出运行,我们仍然可以看到容器的残余物docker ps -a
。在本教程中,您将docker run
多次运行并留下迷路容器会占用磁盘空间。因此,根据经验,我一旦完成容器就会清理容器。为此,您可以运行该docker rm
命令。只需从上面复制容器ID,然后将它们粘贴在命令旁边。
$ docker rm 305297d7a235 ff0a5c3750b9
305297d7a235
ff0a5c3750b9
删除时,您应该看到ID回显给您。如果你要一次删除一堆容器,那么复制粘贴ID可能很繁琐。在这种情况下,你可以简单地运行 -
$ docker rm $(docker ps -a -q -f status=exited)
此命令将删除状态为的所有容器exited
。如果您想知道,该-q
标志只返回数字ID并-f
根据提供的条件过滤输出。最后一件有用的事情是--rm
可以传递的标志,docker run
一旦它退出就自动删除容器。对于一次码头运行,--rm
旗帜非常有用。
在Docker的更高版本中,该docker container prune
命令可用于实现相同的效果。
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
4a7f7eebae0f63178aff7eb0aa39f0627a203ab2df258c1a00b456cf20063
f98f9c2aa1eaf727e4ec9c0283bcaa4762fbdba7f26191f26c97f64090360
Total reclaimed space: 212 B
最后,您还可以删除运行时不再需要的图像docker rmi
。
术语
在上一节中,我们使用了许多特定于Docker的术语,这可能会让一些人感到困惑。因此,在我们进一步讨论之前,让我澄清Docker生态系统中经常使用的一些术语。
- 图像 - 构成容器基础的应用程序蓝图。在上面的演示中,我们使用该
docker pull
命令下载busybox映像。 - 容器 - 从Docker镜像创建并运行实际应用程序。我们使用
docker run
我们下载的busybox图像创建了一个容器。使用该docker ps
命令可以看到正在运行的容器列表。 - Docker守护程序 - 在主机上运行的后台服务,用于管理构建,运行和分发Docker容器。守护程序是在客户端与之通信的操作系统中运行的进程。
- Docker Client - 允许用户与守护进程交互的命令行工具。更一般地说,也可以有其他形式的客户端 - 例如Kitematic,它为用户提供GUI。
- Docker Hub - Docker镜像的注册表。您可以将注册表视为所有可用Docker镜像的目录。如果需要,可以托管自己的Docker注册表,并可以使用它们来提取图像。
使用DOCKER的WEBAPPS
大!所以我们现在看一下docker run
,玩Docker容器,还有一些术语。有了所有这些知识,我们现在已经准备好了解真实的东西,即使用Docker部署Web应用程序!
静态网站
让我们从采取婴儿步骤开始吧。我们要看的第一件事是我们如何运行一个简单的静态网站。我们将从Docker Hub中提取Docker镜像,运行容器并查看运行Web服务器是多么容易。
让我们开始。我们将要使用的图像是一个单页网站,我已经为此演示创建并托管在注册表上- prakhar1989/static-site
。我们可以一次性直接下载并运行图像docker run
。如上所述,该--rm
标志在退出时自动删除容器。
$ docker run --rm prakhar1989/static-site
由于图像不存在于本地,因此客户端将首先从注册表中获取图像,然后运行该图像。如果一切顺利,您应该Nginx is running...
在终端中看到一条消息。好了,现在服务器正在运行,如何查看网站?它在运行什么端口?更重要的是,我们如何直接从主机访问容器?按Ctrl + C停止容器。
好吧,在这种情况下,客户端没有暴露任何端口,所以我们需要重新运行docker run
命令来发布端口。虽然我们在这里,但我们也应该找到一种方法,以便我们的终端不会连接到正在运行的容器。这样,您可以愉快地关闭终端并保持容器运行。这称为分离模式。
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
在上面的命令中,-d
将分离我们的终端,-P
将所有暴露的端口发布到随机端口,最后--name
对应于我们想要给出的名称。现在我们可以通过运行docker port [CONTAINER]
命令来查看端口
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
您可以在浏览器中打开http:// localhost:32769。
注意:如果您使用的是docker-toolbox,那么您可能需要使用它
docker-machine ip default
来获取IP。
您还可以指定客户端将连接转发到容器的自定义端口。
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
要停止分离的容器,请docker stop
通过提供容器ID来运行。在这种情况下,我们可以使用static-site
我们用来启动容器的名称。
$ docker stop static-site
static-site
我相信你同意这很简单。要在真实服务器上部署它,您只需要安装Docker,然后运行上面的Docker命令。现在您已经了解了如何在Docker镜像中运行Web服务器,您一定想知道 - 如何创建自己的Docker镜像?这是我们将在下一节中探讨的问题。
Docker图像
我们之前已经查看了图像,但在本节中我们将深入了解Docker图像并构建我们自己的图像!最后,我们还将使用该图像在本地运行我们的应用程序,最后在AWS上部署以与我们的朋友分享!激动吗?大!让我们开始吧。
Docker镜像是容器的基础。在前面的示例中,我们从注册表中提取了Busybox图像,并要求Docker客户端基于该图像运行容器。要查看本地可用的图像列表,请使用该docker images
命令。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
上面给出了我从注册表中提取的图像列表,以及我自己创建的图像(我们很快就会看到)。的TAG
参考图像的一个特定的快照和IMAGE ID
是该图像的相应的唯一标识符。
为简单起见,你可以认为类似于一个Git仓库的图像-图像可以提交与变化,并有多个版本。如果您未提供特定版本号,则客户端默认为latest
。例如,您可以提取特定版本的ubuntu
图像
$ docker pull ubuntu:18.04
要获得新的Docker镜像,您可以从注册表(例如Docker Hub)获取它,也可以创建自己的。Docker Hub上有数万个图像可供使用。您还可以使用命令行直接搜索图像docker search
。
在图像方面需要注意的一个重要区别是基本图像和子图像之间的差异。
-
基本图像是没有父图像的图像,通常是具有ubuntu,busybox或debian等操作系统的图像。
-
子图像是基于基本图像构建并添加其他功能的图像。
然后是官方和用户图像,可以是基本图像和子图像。
-
官方图像是由Docker的人员正式维护和支持的图像。这些通常只有一个字。在上面的图像,列表
python
,ubuntu
,busybox
和hello-world
图像的官方图片。 -
用户图像是由您和我这样的用户创建和共享的图像。它们构建在基础映像上并添加其他功能。通常,这些格式为
user/image-name
。
我们的第一张照片
现在我们对图像有了更好的理解,现在是时候创建自己的图像了。我们在本节中的目标是创建一个沙盒化简单Flask应用程序的图像。出于本次研讨会的目的,我已经创建了一个有趣的小Flask应用程序,.gif
每次加载时都会显示一只随机猫- 因为你知道,谁不喜欢猫?如果您还没有,请继续在本地克隆存储库,如下所示 -
$ git clone https://github.com/prakhar1989/docker-curriculum.git
$ cd docker-curriculum/flask-app
这应该克隆在运行docker命令的机器上,而不是在docker容器内。
现在,下一步是使用此Web应用程序创建图像。如上所述,所有用户图像都基于基本图像。由于我们的应用程序是用Python编写的,因此我们将要使用的基本映像是Python 3。更具体地说,我们将使用python:3-onbuild
python映像的版本。
onbuild
您可能会问的版本是什么?
这些映像包含多个ONBUILD触发器,这些触发器应该是引导大多数应用程序所需的全部触发器。构建将复制
requirements.txt
文件,pip install
在所述文件上运行RUN ,然后将当前目录复制到/usr/src/app
。
换句话说,onbuild
图像的版本包括帮助自动化使应用程序运行的无聊部分的帮助程序。这些图像不是手动执行这些任务(或编写这些任务的脚本),而是为您工作。我们现在拥有创建自己图像的所有要素 - 一个功能强大的网络应用程序和一个基本图像。我们该怎么做?答案是 - 使用Dockerfile。
Dockerfile
一个Dockerfile是包含泊坞窗客户而创建图像调用命令的列表,一个简单的文本文件。这是一种自动化图像创建过程的简单方法。最好的部分是您在Dockerfile中编写的命令几乎与其等效的Linux命令相同。这意味着您不必学习新语法来创建自己的dockerfiles。
应用程序目录确实包含Dockerfile,但由于我们是第一次这样做,我们将从头开始创建一个。首先,创建于我们最喜欢的文本编辑器,一个新的空白文件并将其保存在同一文件夹中的名称烧瓶应用Dockerfile
。
我们从指定基本图像开始。使用FROM
关键字来做到这一点 -
FROM python:3-onbuild
下一步通常是编写复制文件和安装依赖项的命令。对我们来说幸运的是,onbuild
图像版本可以解决这个问题。我们需要指定的下一件事是需要公开的端口号。由于我们的烧瓶应用程序在端口上运行5000
,这就是我们要指出的。
EXPOSE 5000
最后一步是编写运行应用程序的命令,简单地说就是 - python ./app.py
。我们使用CMD命令来做到这一点 -
CMD ["python", "./app.py"]
主要目的CMD
是告诉容器启动时应该运行哪个命令。有了这个,我们Dockerfile
现在准备好了。这是它的样子 -
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
现在我们有了我们的Dockerfile
,我们可以建立我们的形象。该docker build
命令可以解决从中创建Docker镜像的繁琐问题Dockerfile
。
以下部分显示了运行相同的输出。在您自己运行命令之前(不要忘记句点),请务必将您的用户名替换为您的用户名。此用户名应与您在Docker中注册时创建的用户名相同。如果您还没有这样做,请继续创建一个帐户。该docker build
命令非常简单 - 它带有一个可选的标签名称-t
和包含该目录的目录的位置Dockerfile
。
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
如果您没有python:3-onbuild
图像,客户端将首先拉动图像,然后创建图像。因此,运行命令的输出看起来与我的不同。仔细看,你会发现构建触发器已正确执行。如果一切顺利,你的形象应该准备好了!运行docker images
并查看您的图像是否显示。
本节的最后一步是运行图像,看看它是否真的有效(用你的用户名替换我的用户名)。
$ docker run -p 8888:5000 yourusername/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
我们刚刚运行的命令使用端口5000作为容器内的服务器,并在端口8888上向外部公开。使用端口8888转到URL,您的应用程序应该处于活动状态。
恭喜!您已成功创建第一个泊坞窗图像。