关于程序员:从-0-到-1-构建一个自己的-Docker-应用

4次阅读

共计 6034 个字符,预计需要花费 16 分钟才能阅读完成。

Docker,能够让开发者打包他们的利用以及依赖包到一个轻量级、可移植的容器中,而后公布到任何风行的 Linux 机器上,也能够实现虚拟化。

Docker“真香定律”:不会用的时候感觉简单,用棘手了就再也放不下了。

明天咱们就带大家从 0 到 1 构建一个本人的 Docker 利用。

应用的语言和利用的版本如下:Python 3.8.1,Flask 库 1.1.1,Redis 库 3.4.1。

1. web 利用

这次咱们应用 Python 来编写咱们的 web 利用,上一次咱们应用的是 Go 语言。

因为 Go 语言部署间接应用二进制文件,Dockerfile 会极其简略,为了让大家相熟一下 Dockerfile 的利用,所以这里咱们应用 Python 语言里编写咱们的 web 利用。

1.1 Flask 装置

Flask 装置很简略,和其余 Python 依赖装置根本没有区别。

pip install flask

1.2 Flask demo

咱们后面说了 Flask 是一个十分轻量的 web 框架.

那么有多轻量呢?

轻量到咱们应用上面几行代码就能够构建进去一个简略的 web 利用。

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, Flask'

启动利用。

$ env FLASK_APP=hello.py flask run
 * Serving Flask app "hello"
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

利用默认启动在 5000 端口,咱们能够通过 -p 参数指定援用的启动端口。

当然 Flask 还反对其余参数,咱们能够通过 flask run --help 进行查看。

root@a36d1df88169:/# flask run --help
Usage: flask run [OPTIONS]

  Run a local development server.

  This server is for development purposes only. It does not provide the
  stability, security, or performance of production WSGI servers.

  The reloader and debugger are enabled by default if FLASK_ENV=development
  or FLASK_DEBUG=1.

Options:
  -h, --host TEXT                 The interface to bind to.
  -p, --port INTEGER              The port to bind to.
  --cert PATH                     Specify a certificate file to use HTTPS.
  --key FILE                      The key file to use when specifying a
                                  certificate.
  --reload / --no-reload          Enable or disable the reloader. By default
                                  the reloader is active if debug is enabled.
  --debugger / --no-debugger      Enable or disable the debugger. By default
                                  the debugger is active if debug is enabled.
  --eager-loading / --lazy-loader
                                  Enable or disable eager loading. By default
                                  eager loading is enabled if the reloader is
                                  disabled.
  --with-threads / --without-threads
                                  Enable or disable multithreading.
  --extra-files PATH              Extra files that trigger a reload on change.
                                  Multiple paths are separated by ':'.
  --help                          Show this message and exit.

利用启动了之后,咱们能够拜访 5000 端口来验证利用是不是失常的。

[root@docker ~]# curl localhost:5000
Hello, Flask

1.3 Flask 应用

下面介绍了 Flask 最简略的应用 demo,上面咱们应用 Flask 来编写咱们利用和 Redis 进行交互。

首先咱们也要先装置 Python 依赖库:redis。

pip install redis
咱们次要要实现三个性能:

  1. redis 连贯
  2. 提供一个 route set 实现对 redis 中的值进行设置
  3. 提供一个 route get 实现对 redis 中的值进行查问
redis 连贯

redis 连贯,咱们间接应用 Python 的依赖库 Redis。

import redis

redis_client = redis.Redis(host=redis_host, port=redis_port, db=0)

其中连贯 Redis 须要应用三个参数:

  • host: redis 的 host
  • port: redis 的端口
  • db:redis 中的数据库,咱们应用 db = 0 即可。

这里的一个外围问题是 redis 运行在另外一个 Docker 中,那咱们在利用的 Docker 中如何连贯 redis 实例呢?也就是如何发现 redis 的 host 和 port 呢?

在 Docker 技术中咱们能够在启动 Docker 的时候指定参数 –link 将两个 Docker 的网络进行买通。在上面部署的时候咱们再细说。

set route

编写一个 route,能够对 redis 进行写入。

@app.route('/set')
def set():
    key = request.args.get("key")
    value = request.args.get("value")
    redis_client.set(key, value)
    return 'OK. We have set' + key + 'to be' + value

其中 request.args 中能够获取到 url 中的参数。然而下面的代码没有做参数校验,key 和 value 可能是空,咱们加一个参数校验的逻辑。


@app.route('/set')
def set():
    key = request.args.get("key")
    value = request.args.get("value")
    if key is None or value is None:
        return 'OOps, the key or value is NULL'
    redis_client.set(key, value)
    return 'OK. We have set' + key + 'to be' + value
get route

编写一个 route 对 redis 中的值查问

@app.route('/get')
def get():
    key = request.args.get('key')
    if key is None:
        return 'OOps, the key is null'
    value = redis_client.get(key)
    return value

至此,咱们的 web 利用代码编写实现,残缺的代码如下,其中 redis-host 当初还是一个占位符,咱们部署的时候会把这个变量注入进来。

from flask import Flask, request
import redis

redis_client = redis.Redis(host='redis-host', port=6379, db=0)
app = Flask(__name__)

@app.route('/set')
def set():
    key = request.args.get('key')
    value = request.args.get('value')
    if key is None or value is None:
        return 'OOps, the key or value is NULL'
    redis_client.set(key, value)
    return 'OK. We have set' + key + 'to be' + value

@app.route('/get')
def get():
    key = request.args.get('key')
    if key is None:
        return 'OOps, the key is null'
    value = redis_client.get(key)
    return value

2. Dockerfile

上面开始编写咱们的 Dockerfile。

回顾一下咱们下面编写 web 利用过程中,次要装置了依赖 flask 和 redis 依赖。咱们能够很简略写进去咱们的 Dockerfile 如下,并命名为 Dockerfile。

from python:3

RUN pip install flask
RUN pip install redis
RUN mkdir /data

COPY hello.py /data/
WORKDIR /data

EXPOSE 5000
ENV FLASK_APP=/data/hello.py
ENTRYPOINT ["flask", "run", "-h", "0.0.0.0"]

咱们对这个 Dockerfile 进行一个简略解释:

  • from:示意根底镜像是 python:3;
  • RUN:示意在 docker build 的时候会执行前面的几个命令;
  • COPY:拷贝文件或者目录都能够;
  • WORKDIR:示意启动容器之后,以后的工作目录;
  • EXPOSE:示意容器要裸露 5000 端口;
  • ENV:环境变量;
  • ENTRYPOINT:示意 Docker 容器的启动过程。这里 entrypoint 中的 flask run 咱们减少了参数 -h 0.0.0.0。如果不加这个参数的话,过程默认绑定到 127.0.0.1,里面是没有方法拜访的。

通过该 dockerfile 来构建镜像。根本每一个命令都会对应一个 step,如下。

[root@docker web]# docker build -t web:v1 .
Sending build context to Docker daemon  3.584kB
Step 1/8 : from python:3
 ---> efdecc2e377a
Step 2/8 : RUN pip install flask
 ---> Running in c4dfe7b3e466
Collecting flask
  Downloading Flask-1.1.1-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous>=0.24
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1
  Downloading Jinja2-2.11.1-py2.py3-none-any.whl (126 kB)
Collecting Werkzeug>=0.15
  Downloading Werkzeug-1.0.0-py2.py3-none-any.whl (298 kB)
  .......
Step 8/8 : ENTRYPOINT ["flask", "run"]
 ---> Running in 25594e1de72f
Removing intermediate container 25594e1de72f
 ---> d18b55e4d1fd
Successfully built d18b55e4d1fd
Successfully tagged web:v1

构建胜利之后,咱们能够通过 docker images 查看到咱们方才 build 进去的镜像 web。

[root@docker demo]# docker images | grep web
web                 v1                  02cc264143dc        6 minutes ago       943MB

3. 部署

咱们先来部署一个 Redis Docker,-d 参数示意以 daemon 的形式运行。-p 示意端口映射。-name 示意 Docker 容器的名字叫 redis-test。

docker run --name redis-test -p 6379:6379 -d redis:latest

上面部署咱们的 web 利用。

[root@docker ~]# docker run -p 5000:5000 --link redis-test:redis-host -d --name web web:v1
64eef1f67c3934b6257510f47b587c59cee635188a4043b749966e71d2bc8c08
[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
64eef1f67c39        web:v1              "flask run -h 0.0.0.0"   2 seconds ago       Up 1 second         0.0.0.0:5000->5000/tcp   web

其中有一个运行参数须要进行简略阐明,也就是 –link。

link 前面跟一对映射的值,左侧的为曾经存在的 Docker 容器,右侧的为该容器映射到咱们启动的 Docker 利用中的 host 名字,这里也就是 web 这个 Docker 容器。

咱们上面通过 docker exec 进入到容器中看一下 link 是怎么做的。

[root@docker ~]# docker exec -ti 64eef1f67c39 /bin/bash
root@64eef1f67c39:/data#

咱们查看一下 hosts 文件。

root@64eef1f67c39:/data# cat /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.5    redis-host 0d748e8ce766 redis-test
172.17.0.6    64eef1f67c39

咱们能够看到 redis-host 曾经被写到 hosts 中,所以咱们在 web 这个 Docker 容器中就能够通过 redis-host 这个主机名拜访到 Redis 容器了,这也是咱们的利用代码的写法。

4. 验证

部署实现,咱们上面进行一个简略的验证。在宿主机上执行上面命令去设置一对 kv: <imooc, imooc.com> 写入到 Redis 中。

[root@docker ~]# curl "localhost:5000/set?key=imooc&value=imooc.com"
OK. We have set imooc to be imooc.com

第二个申请去读取该值,如下。

[root@docker ~]# curl "localhost:5000/get?key=imooc"
imooc.com

5. 总结

至此,咱们第一个入手实际的 Docker 利用曾经实现。原本想弄一个更简单的利用,然而限于篇幅,只能做了一下取舍。尽管简略,还是倡议各位同学进行入手实际。毕竟纸上得来终觉浅,绝知此事要躬行。

作者 | legendtkl

本文由 mdnice 多平台公布

正文完
 0