Docker之旅:在Docker容器中创建第一个程序

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Docker的概念Docker是开发人员和系统管理员 使用容器开发,部署和运行应用程序的平台。使用Linux容器来部署应用程序称为集装箱化。

Docker的概念

Docker是开发人员和系统管理员 使用容器开发,部署和运行应用程序的平台。使用Linux容器来部署应用程序称为集装箱化。容器不是新的事物,但它们用于轻松部署应用程序。


一、测试一下Docker的版本

1. 查看Docker版本的信息

运行docker –version并确保您拥有受支持的Docker版本:

root@iZbp162mb58mqtz72o389nZ:~# docker --version
Docker version 18.03.1-ce, build 9ee9f40
root@iZbp162mb58mqtz72o389nZ:~# 

2. 查看Docker的更多的信息

运行docker info或(docker version不–)查看关于docker安装的更多详细信息:

root@iZbp162mb58mqtz72o389nZ:~# docker info
Containers: 3
 Running: 0
 Paused: 0
 Stopped: 3
Images: 1
Server Version: 18.03.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
......

3. 测试Docker安装

通过运行简单的Docker镜像hello-world来测试您的安装是否工作正常 :

root@iZbp162mb58mqtz72o389nZ:~# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash
 ......

4. 列出hello-world下载到您的机器的图像

root@iZbp162mb58mqtz72o389nZ:~# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              e38bc07ac18e        5 weeks ago         1.85kB
root@iZbp162mb58mqtz72o389nZ:~# 

5. 列出hello-world显示消息后退出的容器(由图像衍生)。如果它仍在运行,则不需要该–all选项:

root@iZbp162mb58mqtz72o389nZ:~# docker container ls --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
72b99c9c6652        hello-world         "/hello"            6 minutes ago       Exited (0) 6 minutes ago                       elegant_bhaskara
ef4105062f3c        hello-world         "/hello"            22 hours ago        Exited (0) 22 hours ago                        elegant_shannon
8eeb4f85babc        hello-world         "/hello"            22 hours ago        Exited (0) 22 hours ago                        sleepy_bartik
64c8a1708411        hello-world         "/hello"            22 hours ago        Exited (0) 22 hours ago                        dreamy_ride
root@iZbp162mb58mqtz72o389nZ:~# 

6. Docker的一些命令

## List Docker CLI commands
docker
docker container --help

## Display Docker version and info
docker --version
docker version
docker info

## Execute Docker image
docker run hello-world

## List Docker images
docker image ls

## List Docker containers (running, all, all in quiet mode)
docker container ls
docker container ls --all
docker container ls -aq

二、Docker容器配置

1. 容器所处的位置

现在是开始以Docker方式构建应用程序的时候了。我们从这种应用程序的层次结构的底部开始,这是一个容器,我们将在此页面上介绍。在这个层次上面是一个服务,它定义了容器在生产中的行为方式,最后,在顶层是堆栈。

  • 服务
  • 容器(你在这里)

2. 你新的开发环境

过去,如果您要开始编写Python应用程序,您的第一个业务就是将Python运行开发环境安装到您的机器上。
但是,这会造成您的计算机上的环境需要完美适合您的应用程序按预期运行,并且还需要与您的生产环境相匹配。
使用Docker,您可以将一个可移植的Python运行时作为一个映像获取,无需安装。然后,您的构建可以将基础Python图像与应用程序代码一起包括在内,确保您的应用程序,依赖项和运行时都一起旅行。
这些便携式图像是由称为a的东西定义的Dockerfile

3. 定义一个容器 Dockerfile

Dockerfile定义您的容器内环境中发生了什么。访问网络接口和磁盘驱动器等资源是在此环境中虚拟化的,与系统的其余部分隔离,因此您需要将端口映射到外部世界,并明确要将哪些文件“复制”到那个环境。但是,在完成这些之后,您可以期望在其中定义的应用程序的构建 Dockerfile在其运行的任何位置都完全相同。

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# ls
Dockerfile
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# vi Dockerfile 

编辑一下Dockerfile

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

其中最重要的文件有两个,一个是:requirements.txt,一个是:app.py

4、应用程序本身

再创建两个文件,requirements.txt然后app.py将它们放在同一个文件夹中Dockerfile。这完成了我们的应用程序,您可以看到它非常简单。当上述Dockerfile被内置到的图像,app.py和 requirements.txt是因为存在Dockerfile的ADD命令,并从输出app.py是通过HTTP得益于访问EXPOSE 命令。

  • 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.txt为Python安装Flask和Redis库,并且该应用程序输出环境变量NAME以及调用的输出socket.gethostname()。最后,因为Redis没有运行(因为我们只安装了Python库,而不是Redis本身),所以我们应该期望在这里使用它的尝试失败并产生错误消息。

  • 注意:在容器中访问主机的名称将检索容器ID,这与正在运行的可执行文件的进程ID相似。

好啦,您requirements.txt的系统中不需要Python或其他任何东西,也不需要在系统上安装或运行此映像。看起来你并没有真正用Python和Flask建立一个环境,但是你已经拥有了。

5. 构建应用程序

我们准备构建应用程序。确保您仍然处于新目录的顶层。以下是ls应该显示的内容:

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# ls
Dockerfile  app.py  requirements.txt
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

现在运行build命令。这会创建一个Docker镜像,我们将使用-t它来标记,因此它有一个友好的名称。

ocker build -t friendlyhello .
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker build -t friendlyhello .
Sending build context to Docker daemon  4.608kB
Step 1/7 : FROM python:2.7-slim
 ---> 46ba956c5967
Step 2/7 : WORKDIR /app
 ---> Using cache
 ---> f3b2fb3956fe
......
Successfully tagged friendlyhello:latest
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

我构建的镜像跑到哪里去了?他们在你本地的镜像库里面:friendlyhello这个就是的。

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
friendlyhello       latest              99fa0c4345cf        4 minutes ago       151MB
<none>              <none>              e21d979e3223        6 minutes ago       140MB
python              2.7-slim            46ba956c5967        12 days ago         140MB
hello-world         latest              e38bc07ac18e        5 weeks ago         1.85kB
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

如果有停止一个镜像,可能需要强制停止

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker rmi 99fa0c4345cf --force
Untagged: friendlyhello:latest
Deleted: sha256:99fa0c4345cf9dd423945342f0d2fa4b460e36932edf58c0973fc991e5068d24
Deleted: sha256:f6071820b82680b2eb179a8bc5584451f6e69c2672ef3989040698fa36a66f13
Deleted: sha256:517f33d026cd6ba5ce5433aa4ee575a6e47aa228030c76fda1ffe6ded5abca10
Deleted: sha256:7564cd520ac57faa1032a04f6b7894c09fb08d4e6349c80377d9b74666135274
Deleted: sha256:585d0dbb4c234c5243d8098c175565dc8158968537f4904b5797f6b0aca88977

6、如果有故障了,就看看这里(针对Linux用户的故障排除)

代理服务器在启动并运行后可以阻止与您的网络应用程序的连接。如果您位于代理服务器的后面,请使用以下ENV命令为代理服务器指定主机和端口,将以下行添加到Dockerfile中:

# Set proxy server, replace host:port with values for your servers
ENV http_proxy host:port
ENV https_proxy host:port

代理服务器设置
DNS错误配置可能会产生问题pip。您需要设置您自己的DNS服务器地址才能pip正常工作。您可能需要更改Docker守护程序的DNS设置。您可以/etc/docker/daemon.json使用dns密钥编辑(或创建)配置文件,如下所示:

{
  "dns": ["your_dns_address", "8.8.8.8"]
}

在上面的例子中,列表的第一个元素是你的DNS服务器的地址。第二项是Google的DNS,当第一项不可用时可以使用它。
在继续之前,保存daemon.json并重新启动泊坞窗服务。
sudo service docker restart
一旦修复,重试运行build命令。

7、运行应用程序

运行应用程序,使用以下命令将计算机的端口4000映射到容器的已发布端口80 -p:下面这样就是运行成功了

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker run -p 4000:80 friendlyhello
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

您应该看到Python正在为您的应用提供服务的消息http://0.0.0.0:80。但是该消息来自容器内部,它不知道你将该容器的端口80映射到4000,从而制作正确的URL http://localhost:4000

  • 那么我现在要从外部去访问它,如果是阿里云的话,需要开启安全组
    这里写图片描述
  • 通过ip:端口的方式来访问
    这里写图片描述
  • 后台运行
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker run -p 4000:80 friendlyhello
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
45.76.53.148 - - [17/May/2018 09:29:05] "GET / HTTP/1.1" 200 -
45.76.53.148 - - [17/May/2018 09:29:06] "GET /favicon.ico HTTP/1.1" 404 -

这种方式按Ctrl+C就退出了,不好,我们要在后台运行,只需要多一个-d就可以了。

root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker run -d -p 4000:80 friendlyheol 
ca08a914abea5290bb7cdf422c335b77738fc23e7f6c6ba596165a021daf4584
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

8、查看正在运行的容器(一个程序对应一个容器)

docker container ls
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
ca08a914abea        friendlyhello       "python app.py"     About a minute ago   Up About a minute   0.0.0.0:4000->80/tcp   friendly_minsky
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

9、停止这个程序,结束这个进程

现在docker container stop用来结束这个过程,使用CONTAINER ID如下所示:

//查看container Id
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
ca08a914abea        friendlyhello       "python app.py"     About a minute ago   Up About a minute   0.0.0.0:4000->80/tcp   friendly_minsky
//结束
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker container stop ca08a914abea
ca08a914abea
//没有了
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@iZbp162mb58mqtz72o389nZ:~/docker/pythontest# 

三、分享我的镜像

1.为了演示我们刚才创建的可移植性,我们上传我们构建的映像并在其他地方运行它。毕竟,当您想要将容器部署到生产环境时,您需要知道如何推送注册表。

注册表是存储库的集合,而存储库是图像的集合 - 有点像GitHub存储库,但代码已经创建。注册表上的帐户可以创建许多存储库。该dockerCLI使用公共注册表默认情况下。

注意:我们在这里使用Docker的公共注册表仅仅是因为它是免费和预先配置的,但有许多公共选项可供选择,甚至可以使用Docker Trusted Registry设置您自己的私有注册表。

2.使用您的Docker ID登录

如果您没有Docker帐户,请在cloud.docker.com注册一个帐户 。记下你的用户名。

2.1 登录到本地计算机上的Docker公共注册表。

root@iZbp162mb58mqtz72o389nZ:~# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: xiongben
Password: 
Login Succeeded
root@iZbp162mb58mqtz72o389nZ:~# 

2.2 标记图像

将本地映像与注册表中的存储库相关联的符号是 username/repository:tag。该标签是可选的,但建议使用,因为它是注册管理机构用于为Docker镜像提供版本的机制。为该上下文提供存储库并标记有意义的名称,例如 get-started:part2。这将图像放入get-started存储库并标记为part2。
现在,把它放在一起来标记图像。docker tag image使用您的用户名,存储库和标签名称运行,以便将图像上传到您想要的目的地。该命令的语法是:

docker tag image username/repository:tag

运行如下:

root@iZbp162mb58mqtz72o389nZ:~# docker tag friendlyhello xiongben/get-started:part2

2.3 需要去创建一个docker的仓库

例如我创建了一个get-started。
docke cloud
这里写图片描述

2.4 运行docker图像ls以查看新标记的图像。

root@iZbp162mb58mqtz72o389nZ:~# docker image ls
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
friendlyhello          latest              7f2dee16bc71        2 hours ago         151MB
xiongben/get-started   part2               7f2dee16bc71        2 hours ago         151MB
<none>                 <none>              e21d979e3223        2 hours ago         140MB
python                 2.7-slim            46ba956c5967        12 days ago         140MB
hello-world            latest              e38bc07ac18e        5 weeks ago         1.85kB

2.5 发布镜像

root@iZbp162mb58mqtz72o389nZ:~# docker push xiongben/get-started:part2
The push refers to repository [docker.io/xiongben/get-started]
bb1832784221: Pushed 
3769158c31ac: Pushed 
2ac6ade48cac: Pushed 
a40d037570f2: Mounted from library/python 
4e1a46391216: Mounted from library/python 
10dd6271862c: Mounted from library/python 
ba291263b085: Mounted from library/python 
part2: digest: sha256:ce25797c1fb3d95fc7393f015ea584be0c110e0469e186813ee755f41f76922a size: 1787
root@iZbp162mb58mqtz72o389nZ:~# 

2.6 看下这样就成功了

root@iZbp162mb58mqtz72o389nZ:~# docker push xiongben/get-started:part2
The push refers to repository [docker.io/xiongben/get-started]
bb1832784221: Pushed 
3769158c31ac: Pushed 
2ac6ade48cac: Pushed 
a40d037570f2: Mounted from library/python 
4e1a46391216: Mounted from library/python 
10dd6271862c: Mounted from library/python 
ba291263b085: Mounted from library/python 
part2: digest: sha256:ce25797c1fb3d95fc7393f015ea584be0c110e0469e186813ee755f41f76922a size: 1787
root@iZbp162mb58mqtz72o389nZ:~# 

四、从远程存储库中提取并运行图像

从现在开始,您可以使用docker run此命令在任何机器上使用并运行您的应用程序

docker run -p 4000:80 username/repository:tag

那么来运行一下试一试:

root@iZbp162mb58mqtz72o389nZ:~# docker run -p 4000:80 xiongben/get-started:part2
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

访问一下:
这里写图片描述

  • 无论在哪里docker run执行,它都会将您的图像,Python以及所有依赖项从中拉出requirements.txt,然后运行您的代码。它们都在一个整洁的小包中一起旅行,并且您不需要在主机上安装任何Docker来运行它(意思是这样你的机器上安装的docker环境,你不需要再将程序传上去,直接从cloud上拉出来,就可以运行了)。

好啦,完成啦!

目录
相关文章
|
11天前
|
监控 数据管理 pouch
Docker容器技术概览
关于Docker容器技术的概览,包括Docker的优势、劣势、核心技术、容器所依赖的技术,以及Docker容器的管理和编排工具。
39 7
Docker容器技术概览
|
10天前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
10天前
|
NoSQL 应用服务中间件 Redis
Docker跨宿主机容器通信-通过网络跨宿主机互联
这篇文章介绍了Docker容器跨宿主机通信的实现方法,包括Docker的四种网络模式(host、none、container、bridge)以及如何通过修改网络配置和添加路由规则来实现不同宿主机上的容器之间的互联。
31 0
Docker跨宿主机容器通信-通过网络跨宿主机互联
|
10天前
|
应用服务中间件 nginx Docker
Docker同一台宿主机容器通信-通过容器名称互联
本文详细介绍了如何通过容器名称实现同一宿主机上容器间的互联,并提供了实战案例。首先,文章解释了容器间通过自定义名称访问的原理,随后演示了创建并连接Tomcat与Nginx容器的具体步骤。此外,还讨论了配置中可能出现的问题及解决方案,包括避免硬编码IP地址和使用自定义容器别名来增强系统的灵活性与可维护性。通过这些实践,展示了如何高效地配置容器间通信,确保服务稳定可靠。
16 1
Docker同一台宿主机容器通信-通过容器名称互联
|
3天前
|
持续交付 开发者 Docker
掌握 Docker:容器化技术在现代开发中的应用
Docker 是一个开源容器化平台,使开发者能够将应用程序及其依赖项封装在轻量级容器中,确保跨平台的一致性。本文介绍了 Docker 的基本概念、核心组件及优势,并展示了其在快速部署、一致性、可移植性和微服务架构中的应用。通过示例说明了 Docker 在本地开发环境搭建、服务依赖管理和 CI/CD 流程中的作用,以及多阶段构建、资源限制和网络模式等高级特性。掌握 Docker 可大幅提升开发效率和应用管理能力。
|
11天前
|
应用服务中间件 Shell nginx
Docker容器操作基础命令
关于Docker容器操作基础命令的教程,涵盖了从启动、查看、删除容器到端口映射和容器信息获取的一系列常用命令及其使用方法。
51 14
|
8天前
|
运维 安全 开发者
Docker容器技术
Docker容器技术
28 6
|
8天前
|
Cloud Native 持续交付 Docker
云原生技术实践:Docker容器化部署教程
【9月更文挑战第4天】本文将引导你了解如何利用Docker这一云原生技术的核心工具,实现应用的容器化部署。文章不仅提供了详细的步骤和代码示例,还深入探讨了云原生技术背后的哲学,帮助你理解为何容器化在现代软件开发中变得如此重要,并指导你如何在实际操作中运用这些知识。
|
8天前
|
负载均衡 大数据 测试技术
docker容器技术有哪些应用场景?
docker容器技术有哪些应用场景?
19 5
|
15天前
|
Cloud Native 持续交付 Docker
云原生之旅:Docker容器化实战指南
【8月更文挑战第29天】本文将引领你进入云原生技术的世界,以Docker容器化为切入点,深入浅出地介绍如何利用Docker进行应用的打包、部署及管理。我们将通过实际代码示例,一步步展示Docker镜像的构建过程,以及如何运行和管理这些容器。无论你是初学者还是有一定经验的开发者,都能从中获得宝贵的知识和实操经验。