Docker 教程-入门知识-容器

这篇博客介绍了如何使用Docker构建和运行容器。首先,确保安装了Docker并满足前提条件。通过Dockerfile定义容器环境,包括Python应用的dependencies。使用Dockerfile构建镜像,然后运行容器,映射端口。最后,学习如何分享和从远程仓库拉取镜像。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

容器

前提条件

介绍

  • 是时候开始用 Docker 的方式构建一个应用程序了。我们从这类应用程序的层次结构的底部开始,一个容器,即本博客关注的内容。在这个级别之上是一个服务,它定义了容器在生产中的行为,在Docker 教程-入门知识-服务中介绍。最后,在顶层是堆栈,定义了所有服务的交互,在Docker 教程-入门知识-栈中介绍。
    • 服务
    • 容器化(你在这里)

新开发环境

  • 在过去,如果您要开始编写一个python应用程序,您要做的第一件事情是在您的机器上安装一个python运行时环境。但是,这就产生了这样一种情况,即您的计算机上的环境需要非常适合您的应用程序按预期运行,而且还需要与您的生产环境相匹配。

  • 使用Docker,您只需获取一个可移植的python运行时环境作为镜像,不需要安装。然后,您的构建可以将基本的python镜像和应用程序代码放在一起,确保应用程序、其依赖项和运行时环境一起被运送。

  • 这些可移植镜像是由一个称为 Dockerfile 的东西定义的。

通过 Dockerfile 定义容器

  • Dockerfile 定义容器内环境中发生的事情。对网络接口和磁盘驱动器等资源的访问在该环境中进行了虚拟化,该环境与系统的其他部分隔离,因此您需要将端口映射到外部世界,并具体说明要将哪些文件“复制”到该环境中。但是,这样做之后,您可以期望在这个 Dockerfile 中定义的应用程序的构建在运行的任何地方的行为都完全相同。
  • 下面以 Python 应用来举例说明,如果是 Java 应用,请参考:https://github.com/docker/labs/tree/master/developer-tools/java

Dockerfile

  • 在本地计算机上创建一个空目录。将目录(cd)更改为新目录,创建一个名为 Dockerfile 的文件,将以下内容复制并粘贴到该文件中,然后保存。注意新 Dockerfile 中每个语句的注释解释了该语句的含义。
    • # 使用一个官方的 Python 运行时环境作为父镜像
      FROM python:2.7-slim
      
      # 把工作目录设置为 /app
      WORKDIR /app
      
      # 把当前目录的内容拷贝到 /app 目录的容器
      COPY . /app
      
      # 安装由 requirements.txt 指定的需要的包
      RUN pip install --trusted-host pypi.python.org -r requirements.txt
      
      # 将端口 80 提供给此容器之外的世界
      EXPOSE 80
      
      # 定义环境变量
      ENV NAME World
      
      # 当容器启动时运行 app.py
      CMD ["python", "app.py"]    
      
  • 这个 Dockerfile 引用到了一些我们还没有创建的文件,即app.pyrequirements.txt。接下来我们来创建这些文件。

应用

  • 再创建两个文件,requirements.txtapp.py,并将它们与 Dockerfile 放在同一个文件夹中。这就完成了我们的应用程序,正如您所看到的,这非常简单。当上述 Dockerfile 构建镜像时,由于 Dockerfilecopy 命令,app.pyrequirements.txt会被提供,并且通过expose命令可以通过http访问app.py的输出。

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)
  • 现在我们看到pip install-r requirements.txtpython安装flaskredis库,该应用程序打印环境变量 NAME 以及对socket.gethostname()的调用的输出。最后,因为redis没有运行(因为我们只安装了python库,而不是redis本身),所以我们应该期望在这里redis调用失败并产生错误消息。
    • 注意:当在容器中访问主机名时,会检索容器ID,这类似于正在运行的可执行文件的进程ID。
  • 就这样!不需要您系统上有pythonrequirements.txt中的任何内容,在您系统上运行此映像也不会安装这些东西。看起来您并没有真正用PythonFlask建立环境,但是您已经建立了。

构建应用

  • 我们已经准备好构建应用程序了。请确保您仍在新目录的顶层。下面是ls应该显示的内容:
    • 在这里插入图片描述
  • 现在运行build命令。这将创建一个docker映像,我们将使用--tag选项来命名它。如果要使用较短的选项,请使用-t
    • 命令:docker build --tag=friendlyhello .
    • 在这里插入图片描述
  • 你的构建镜像在哪里?它在你机器的本地Docker镜像注册表中
    • 命令: docker image ls

    • 在这里插入图片描述

  • 注意标签是如何默认为最新的。标记选项的完整语法是--tag=friendlyhello:v0.0.1
  • Linux用户故障排除:
    • 代理服务器设置
      • 代理服务器一旦启动并运行,就可能阻止与Web应用程序的连接。如果您在代理服务器后面,请使用ENV命令为代理服务器指定主机和端口,将以下行添加到Dockerfile中:
      •  # 设置代理服务器,替换 host:port 为你的服务器对应的值
         ENV http_proxy host:port
         ENV https_proxy host:port      
        
    • DNS 设置
      • DNS配置错误会导致 pip 出现问题。您需要设置自己的DNS服务器地址以使 pip 正常工作。您可能需要更改 docker 守护进程的DNS设置。您可以编辑(或创建)/etc/docker/daemon.json配置文件并配置 dns key,如下所示:
      •  {
           "dns": ["your_dns_address", "8.8.8.8"]
         }       
        
      • 在上面的示例中,列表的第一个元素是你的DNS服务器的地址。第二项是谷歌的DNS,当第一项不可用时可以使用。
      • 继续之前,请保存daemon.json并重新启动docker服务。
      • sudo service docker restart
      • 修复后,请重试运行build命令。

运行应用

  • 运行应用程序,使用-p将计算机的端口4000映射到容器的已发布端口80
    • docker run -p 4000:80 friendlyhello
  • 您应该看到一条消息,说python正在为提供服务:http://0.0.0.0:80/。但该消息来自容器内部,它不知道您将该容器的端口80映射到了4000,使得正确的URL变成: http://localhost:4000
  • 可以在浏览器上访问这个URL:
    • 在这里插入图片描述
  • 你也可以在 shell 中通过 curl 命令查看到同样的内容:
    • curl http://localhost:4000
      在这里插入图片描述
  • 4000:80端口的重新映射演示了 Dockerfile 中的EXPOSE 与运行docker run -p时的publish值之间的区别。在后面的步骤中,将主机上的端口4000映射到容器中的端口80,并使用http://localhost
  • 在终端窗口按 CTRL+C 即可停止容器。
  • 现在让我们在后台以分离模式运行应用程序:
    • docker run -d -p 4000:80 friendlyhello
    • 在这里插入图片描述
  • 你得到了你的应用程序的长容器ID,然后被踢回你的终端。您的容器正在后台运行。您还可以通过 docker container ls 查看缩写容器id(在运行命令时两者都可以互换工作):
    • 在这里插入图片描述
  • 注意 CONTAINER IDhttp://localhost:4000 对应的容器匹配。
  • 现在使用 docker container stop 结束进程,使用 CONTAINER ID,如下所示:
    • docker container stop 7e20f03f9e86
    • 在这里插入图片描述

分享镜像

  • 为了演示我们刚刚创建的内容的可移植性,让我们上传构建的镜像并在其他地方运行它。毕竟,当您想要将容器部署到生产环境中时,您需要知道如何推送到注册表。
  • 注册表是存储库的集合,存储库是类似于GitHub存储库的镜像集合,但它的代码已经构建的。注册表中的帐户可以创建多个存储库。默认情况下,docker CLI 使用Docker的公共注册表。
  • 注意:我们在这里使用Docker的公共注册表仅仅是因为它是免费的和预配置的,但是有许多公共注册表可供选择,您甚至可以使用Docker Trusted Registry建立自己的私有注册表。

登录注册表系统

  • 如果没有账号,可以先前往注册:https://hub.docker.com/
  • 在本地登录Docker的公共注册表
    • docker login
    • 在这里插入图片描述

标记镜像

  • 将本地镜像与注册表上的存储库关联的表示法是username/repository:tagtag是可选的,但建议使用,因为它是注册中心用来给Docker镜像提供版本的机制。根据上下文给repositorytag取有意义的名称,如get-started:part2。这会将镜像放入“get-started”存储库,并将其标记为part2
  • 现在,把它们放在一起标记镜像。使用用户名、存储库和标记名运行 docker tag image,以便将镜像上载到所需的目的地。命令的语法为:
    • docker tag image username/repository:tag
  • 例如:
    • docker tag friendlyhello andywannasing/get-started:part2
  • 运行docker image ls查看新标记的镜像
    • 在这里插入图片描述

发布镜像

  • 将您的标记镜像上载到存储库
    • docker push username/repository:tag
    • 在这里插入图片描述
  • 完成后,此上载的结果将公开。如果您登录到Docker Hub,您将在那里看到新的镜像及其pull命令
    • 在这里插入图片描述

从远程仓库拉取并运行镜像

  • 从现在开始,你可以使用docker run在任何机器上运行你的应用程序,命令如下:
    • docker run -p 4000:80 username/repository:tag
  • 如果机器上的镜像在本地不可用,Docker会将其从存储库中提取出来。
    • 例如,命令:docker run -p 4000:80 andywannasing/get-started:part2
    • 在这里插入图片描述
  • 无论docker在哪里运行,它都会拉取您的镜像,以及 Python 和 requirements.txt 中的所有依赖项,并运行您的代码。所有这些都以一个整洁的小程序包一起传输,您不需要在主机上安装任何东西,Docker就可以运行它。

小结

摘要和备忘录

docker build -t friendlyhello .  # 使用当前路径的 Dockerfile 来创建镜像
docker run -p 4000:80 friendlyhello  # 运行"friendlyhello" 镜像,并把 4000 端口(容器外部)映射到 80(容器内部)
docker run -d -p 4000:80 friendlyhello         # 和上面的命令同样的效果,但是以后台分离的模式运行
docker container ls                                # 显示所有运行中的容器列表
docker container ls -a             # 显示所有容器列表,即使处于非运行状态也显示
docker container stop <hash>           # 优雅地停止指定的容器
docker container kill <hash>         # 强制停止指定的容器
docker container rm <hash>        # 从当前机器移除指定容器
docker container rm $(docker container ls -a -q)         # 移除所有的容器
docker image ls -a                             # 列出所有镜像列表
docker image rm <image id>            # 从当前机器移除指定镜像
docker image rm $(docker image ls -a -q)   # 从当前机器移除所有镜像
docker login             # 使用 Docker 凭据登录 CLI 会话
docker tag <image> username/repository:tag  # 标记镜像以上传注册表
docker push username/repository:tag            # 上传镜像到注册表
docker run username/repository:tag                   # 从注册表中拉取镜像并运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值