# 将官方 Python 运行时用作父镜像
FROM python:3.6.8

# 将工作目录设置为 /app
WORKDIR /app

# 将当前目录内容复制到位于 /app 中的容器中
ADD . /app

# 安装 requirements.txt 中指定的任何所需软件包
RUN pip install -r requirements.txt

# 使端口 80 可供此容器外的环境使用
EXPOSE 80

# 定义环境变量
ENV NAME World

# 在容器启动时运行 app.py
CMD ["python", "app.py"]

2. 提供依赖文件

2.1. requirements.txt

Flask
Redis

2.2. 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)

3. 构建应用

root@VM_0_7_centos p]# ls
app.py  Dockerfile  requirements.txt

[root@VM_0_7_centos p]# docker build -t friendlyhello .
Sending build context to Docker daemon  4.608kB
Step 1/7 : FROM python:3.6.8
3.6.8: Pulling from library/python
741437d97401: Already exists 
34d8874714d7: Already exists 
0a108aa26679: Already exists 
7f0334c36886: Already exists 
65c95cb8b3be: Already exists 
36185429e34c: Pull complete 
99d78cb27656: Pull complete 
735a9c9a10ba: Pull complete 
aa45785265a0: Pull complete 
Digest: sha256:00110125bd9c23f200cfd2cfa82e68b8ab2006e1358f7a048e005794aa51568f
Status: Downloaded newer image for python:3.6.8
 ---> e0a418687f6c
Step 2/7 : WORKDIR /app
 ---> Running in 5402422af25a
Removing intermediate container 5402422af25a
 ---> e1f264441e23
Step 3/7 : ADD . /app
 ---> 36cf6907a33f
Step 4/7 : RUN pip install -r requirements.txt
 ---> Running in 1f1a15b13b08
Collecting Flask (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
Collecting Redis (from -r requirements.txt (line 2))
  Downloading https://files.pythonhosted.org/packages/d0/8b/c43ef27d02382853b22c49bc41a8389e47d60811dd1d72b9a45bc905a5f8/redis-3.2.0-py2.py3-none-any.whl (65kB)
Collecting Werkzeug>=0.14 (from Flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Collecting itsdangerous>=0.24 (from Flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting click>=5.1 (from Flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
Collecting Jinja2>=2.10 (from Flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->Flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/08/04/f2191b50fb7f0712f03f064b71d8b4605190f2178ba02e975a87f7b89a0d/MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl
Installing collected packages: Werkzeug, itsdangerous, click, MarkupSafe, Jinja2, Flask, Redis
Successfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.1.0 Redis-3.2.0 Werkzeug-0.14.1 click-7.0 itsdangerous-1.1.0
Removing intermediate container 1f1a15b13b08
 ---> 4b5a84e8ba00
Step 5/7 : EXPOSE 80
 ---> Running in 3f41d16ac324
Removing intermediate container 3f41d16ac324
 ---> e757e6f67a39
Step 6/7 : ENV NAME World
 ---> Running in 72edb9f98355
Removing intermediate container 72edb9f98355
 ---> 7dafe4033354
Step 7/7 : CMD ["python", "app.py"]
 ---> Running in bfbd6350bd43
Removing intermediate container bfbd6350bd43
 ---> 0667cb3d8f91
Successfully built 0667cb3d8f91
Successfully tagged friendlyhello:latest

4. 运行应用

# docker run -d -p 4000:80 friendlyhello
d5ef6edaa6d1e7df9bd6d997a0c672a8e2d43895c7db0c5ff373b681e84849f0

# curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> d5ef6edaa6d1<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
d5ef6edaa6d1        friendlyhello       "python app.py"     4 seconds ago       Up 3 seconds        0.0.0.0:4000->80/tcp   priceless_chebyshev

停止应用
# docker stop d5ef6edaa6d1

5. 发布镜像

  • 在cloud.docker.com网站注册
  • docker login 命令登录
  • 标记本地镜像:docker tag friendlyhello timscm/get-started:part1
  • 发布镜像: docker push timscm/get-started:part1
  • 下载远程镜像(测试目的,可能需要先删除已存在的镜像):docker run -p 4000:80 timscm/get-started:part1

 

[root@VM_0_7_centos ~]# 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: timscm
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@VM_0_7_centos ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
friendlyhello       latest              0667cb3d8f91        19 minutes ago      932MB
python              3.6.8               e0a418687f6c        7 days ago          922MB
python              latest              ac069ebfe1e1        7 days ago          927MB
hello-world         latest              fce289e99eb9        7 weeks ago         1.84kB
[root@VM_0_7_centos ~]# docker tag image timscm/get-started:part1
Error response from daemon: No such image: image:latest
[root@VM_0_7_centos ~]# docker tag friendlyhello timscm/get-started:part1
[root@VM_0_7_centos ~]# docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
friendlyhello        latest              0667cb3d8f91        20 minutes ago      932MB
timscm/get-started   part1               0667cb3d8f91        20 minutes ago      932MB
python               3.6.8               e0a418687f6c        7 days ago          922MB
python               latest              ac069ebfe1e1        7 days ago          927MB
hello-world          latest              fce289e99eb9        7 weeks ago         1.84kB
[root@VM_0_7_centos ~]# docker push timscm/get-started:part1
The push refers to repository [docker.io/timscm/get-started]
c21f48b71c61: Pushed 
599fd8743518: Pushed 
07de0bdbb7e4: Pushed 
195394b646ef: Mounted from library/python 
f50f856f49fa: Mounted from library/python 
80b43ad4adf9: Mounted from library/python 
14c77983a1cf: Mounted from library/python 
a22a5ac18042: Mounted from library/python 
6257fa9f9597: Mounted from library/python 
578414b395b9: Mounted from library/python 
abc3250a6c7f: Mounted from library/python 
13d5529fd232: Mounted from library/python 
part1: digest: sha256:6e167aed79463d62a48d0dffaf9e70c1e030e34ce09120bd020b0fe3b9178f7c size: 2843
[root@VM_0_7_centos ~]# docker run -d -p 4000:80 timscm/get-started:part1
96092534319b79111e7bf3343eb99409fa9ea0d5b87e7aa7eec6facacd98421d
[root@VM_0_7_centos ~]# docker images -q
0667cb3d8f91
0667cb3d8f91
e0a418687f6c
ac069ebfe1e1
fce289e99eb9
[root@VM_0_7_centos ~]# docker rmi $(docker images -q)
Untagged: python:latest
Untagged: python@sha256:fb877e7ea5c40de100534c6d6f515c486247bfd899cb2767f2de0e876a8127fa
Deleted: sha256:ac069ebfe1e184fc65f70cf83dbb4eeee0c495dbba6757954c130e4125e674e6
Deleted: sha256:926dd46f86107116ae928b9efa391acc9d2efd2656e0f15117139dfc817fb074
Deleted: sha256:70cea1735c6327330cf2c69a48fa543b6f83de73288228047a579c6b31ddcf17
Deleted: sha256:3d46a7823c655242fec7260b8e77a19e3ddf954555f11e91f983a84a0c4b01b2
Deleted: sha256:9f1a83701a94dae5b5546c0cc5d4af12fc215002b79437cef0320c586bd959a7
Error response from daemon: conflict: unable to delete 0667cb3d8f91 (cannot be forced) - image is being used by running container 96092534319b
Error response from daemon: conflict: unable to delete 0667cb3d8f91 (cannot be forced) - image is being used by running container 96092534319b
Error response from daemon: conflict: unable to delete e0a418687f6c (cannot be forced) - image has dependent child images
Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container ebf4c60de4b6
[root@VM_0_7_centos ~]# docker ps 
CONTAINER ID        IMAGE                      COMMAND             CREATED              STATUS              PORTS                  NAMES
96092534319b        timscm/get-started:part1   "python app.py"     About a minute ago   Up About a minute   0.0.0.0:4000->80/tcp   nostalgic_brahmagupta
[root@VM_0_7_centos ~]# docker stop 96092534319b
96092534319b
[root@VM_0_7_centos ~]# docker images 
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
friendlyhello        latest              0667cb3d8f91        24 minutes ago      932MB
timscm/get-started   part1               0667cb3d8f91        24 minutes ago      932MB
python               3.6.8               e0a418687f6c        7 days ago          922MB
hello-world          latest              fce289e99eb9        7 weeks ago         1.84kB
[root@VM_0_7_centos ~]# docker rmi $(docker images -q)
Error response from daemon: conflict: unable to delete 0667cb3d8f91 (must be forced) - image is referenced in multiple repositories
Error response from daemon: conflict: unable to delete 0667cb3d8f91 (must be forced) - image is referenced in multiple repositories
Error response from daemon: conflict: unable to delete e0a418687f6c (cannot be forced) - image has dependent child images
Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container ebf4c60de4b6
[root@VM_0_7_centos ~]# docker rmi -f $(docker images -q)
Untagged: friendlyhello:latest
Untagged: timscm/get-started:part1
Untagged: timscm/get-started@sha256:6e167aed79463d62a48d0dffaf9e70c1e030e34ce09120bd020b0fe3b9178f7c
Deleted: sha256:0667cb3d8f915c1fb390f0f27d7f573771771b1f8c3a08ca60778fba36d867f7
Deleted: sha256:7dafe4033354697ee5e0100a1abda609fcdf9641f9c9026c9df1b8ddac7b2613
Deleted: sha256:e757e6f67a39c40b8d7efb150c658a1eb9a7ec2dd9056c98fc944718cc22f10e
Deleted: sha256:4b5a84e8ba00246ebc717a3dda8506745644bb33c45bafdbd6dbc8f0730636c1
Deleted: sha256:36cf6907a33f4bd53ab7c55f07e4f91d374c4011b89fd55cf34b85100a788423
Deleted: sha256:e1f264441e2316d6b2f4c422b8319b2e50ef089e6ef2d2a9d8e3e050b1ea94bf
Untagged: python:3.6.8
Untagged: python@sha256:00110125bd9c23f200cfd2cfa82e68b8ab2006e1358f7a048e005794aa51568f
Deleted: sha256:e0a418687f6c53e1c097b413ab16306dbfc1d530498fbac64fbd5373cd8f885b
Untagged: hello-world:latest
Untagged: hello-world@sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Error: No such image: 0667cb3d8f91
[root@VM_0_7_centos ~]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@VM_0_7_centos ~]# docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@VM_0_7_centos ~]# docker run -d -p 4000:80 timscm/get-started:part1
Unable to find image 'timscm/get-started:part1' locally
part1: Pulling from timscm/get-started
741437d97401: Already exists 
34d8874714d7: Already exists 
0a108aa26679: Already exists 
7f0334c36886: Already exists 
65c95cb8b3be: Already exists 
36185429e34c: Already exists 
99d78cb27656: Already exists 
735a9c9a10ba: Already exists 
aa45785265a0: Already exists 
ac35858a33a0: Already exists 
5288ebc86076: Already exists 
7c5bb950aa22: Already exists 
Digest: sha256:6e167aed79463d62a48d0dffaf9e70c1e030e34ce09120bd020b0fe3b9178f7c
Status: Downloaded newer image for timscm/get-started:part1
7c449713451aac9e6fa7a5cb64b289283e5afa203262e5cfc8cd5eec4b55645d
[root@VM_0_7_centos ~]# docker images 
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
timscm/get-started   part1               0667cb3d8f91        25 minutes ago      932MB
[root@VM_0_7_centos ~]# docker images -a
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
timscm/get-started   part1               0667cb3d8f91        25 minutes ago      932MB
[root@VM_0_7_centos ~]# docker ps
CONTAINER ID        IMAGE                      COMMAND             CREATED             STATUS              PORTS                  NAMES
7c449713451a        timscm/get-started:part1   "python app.py"     14 seconds ago      Up 13 seconds       0.0.0.0:4000->80/tcp   gifted_swartz
[root@VM_0_7_centos ~]# curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 7c449713451a<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
[root@VM_0_7_centos ~]#