当前位置: 首页 > article >正文

从 0 到 1 构建自己的 Docker 应用

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!

作者| 慕课网精英讲师 legendtkl

在日常开发或者生产环境中,很多情况下,我们的系统都不是一个应用可以搞定的,而是由很多个部分组成,比如 webapp,数据库,缓存等。所以这一章的例子,我们就以一个 web 应用 + 缓存 redis 作为例子构建一个稍微复杂点的应用。

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

1. web 应用

这次我们使用 Python 来编写我们的 web 应用,上一次我们使用的是 Go 语言。由于 Go 语言部署直接使用二进制文件,Dockerfile 会极其的简单,为了让大家熟悉一下 Dockerfile 的应用,所以这里我们使用 Python 语言里编写我们的 web 应用。

Python 语言相信大家都很熟悉,不熟悉也没有关系,代码都很简单。基于 Python 的 web 网络应用框架比较出名的有 Django,Tornado,Flask 等。我们这里使用 Flask 来构建我们的应用,因为 Flask 是一种极其轻量的框架,正如作者所说:

Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. It began as a simple wrapper around Werkzeug and Jinja and has become one of the most popular Python web application frameworks.

Flask offers suggestions, but doesn’t enforce any dependencies or project layout. It is up to the developer to choose the tools and libraries they want to use. There are many extensions provided by the community that make adding new functionality easy.

关于 Flask 的更多信息,可以参考 Flask 的官方网站或者 Github 主页。

1.1 Flask 安装

Flask 安装很简单,和其他 Python 依赖安装基本没有区别。

pip install flask

1.2 Flask demo

我们前面说了 Flask 是一个非常轻量的 web 框架,那么有多轻量呢?轻量到我们使用下面几行代码就可以构建出来一个简单的 web 应用。

from flask import Flaskapp = 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 thestability, security, or performance of production WSGI servers.The reloader and debugger are enabled by default if FLASK_ENV=developmentor 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 acertificate.--reload / --no-reload          Enable or disable the reloader. By defaultthe reloader is active if debug is enabled.--debugger / --no-debugger      Enable or disable the debugger. By defaultthe debugger is active if debug is enabled.--eager-loading / --lazy-loaderEnable or disable eager loading. By defaulteager loading is enabled if the reloader isdisabled.--with-threads / --without-threadsEnable 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 redisredis_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 redisredis_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:3RUN pip install flask
RUN pip install redis
RUN mkdir /dataCOPY hello.py /data/
WORKDIR /dataEXPOSE 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 flaskDownloading Flask-1.1.1-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous>=0.24Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1Downloading Jinja2-2.11.1-py2.py3-none-any.whl (126 kB)
Collecting Werkzeug>=0.15Downloading 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 应用已经完成。本来想弄一个更复杂的应用,但是限于篇幅,只能做了一下取舍。虽然简单,还是建议各位同学进行动手实践。毕竟纸上得来终觉浅,绝知此事要躬行。

欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/299954.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章:

从 0 到 1 构建自己的 Docker 应用

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注&#xff01; 作者| 慕课网精英讲师 legendtkl 在日常开发或者生产环境中&#xff0c;很多情况下&#xff0c;我们的系统都不是一个应用可以搞定的&#xff0c;而是由很…...

照片变漫画怎么做?分享这几个照片变漫画的技巧给你

大家在网上是否有看到过一些绘画博主给别人画漫画图呢&#xff1f;这些图片中的人物形象与现实中的非常相像&#xff0c;而且看起来真的很像漫画中的人物一般&#xff0c;画出来对于一些没有绘画功底的人来说是比较困难的。那么我们又该如何得到我们在漫画中的图片呢&#xff1…...

客运车票网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 题目&#xff1a;基于Wb的公路客运车票信息管理系统设计与实现 时了解客运站动态。 角色&#xff1a;乘客、管理员 (2)车…...

Python利用pandas处理Excel数据的应用

最近迷上了高效处理数据的pandas&#xff0c;其实这个是用来做数据分析的&#xff0c;如果你是做大数据分析和测试的&#xff0c;那么这个是非常的有用的&#xff01;&#xff01;但是其实我们平时在做自动化测试的时候&#xff0c;如果涉及到数据的读取和存储&#xff0c;那么…...

如何指定标签在页面中显示的位置

如何指定标签在页面中显示的位置 在HTML页面设计中常常需要调整标签&#xff08;元素&#xff09;的位置&#xff0c;那么&#xff0c;如何指定标签在页面中显示的位置呢&#xff1f; 使用标签的align属性指定标签在页面中显示的位置&#xff0c;如align"left|right|cen…...

[附源码]Python计算机毕业设计SSM基于java旅游信息分享网站(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…...

Kubernetes——Debug Static Pod

1. 问题背景 注意&#xff0c;我这里的Static Pod并非Kubernetes的Static Pod&#xff0c;而是需要把想要Debug的程序放到Delve环境中重新打包一个镜像。因为还有另外一种场景&#xff0c;那就是我们需要不重启Running Pod&#xff0c;为了和这种方式区分&#xff0c;才以此为…...

Docker常用容器命令

常用容器命令 有镜像才能创建容器&#xff0c;这是根本前提(下载一个ubuntu镜像演示) docker pull ubuntu:18.04 新建并启动容器 格式&#xff1a; docker run [OPTIONS] IMAGE [COMMAND] [ARG…] 参数说明&#xff1a; OPTIONS说明&#xff08;常用&#xff09;&#xff1a…...

为什么 char[] 优于 String 的密码?

问&#xff1a; 在 Swing 中&#xff0c;密码字段有一个 getPassword()&#xff08;返回 char[]&#xff09;方法&#xff0c;而不是通常的 getText()&#xff08;返回 String&#xff09;方法。同样&#xff0c;我遇到了一个建议&#xff0c;不要使用 String 来处理密码。 为…...

如何识别网络应用层协议?

能够标识出 Internet上每个流所使用的应用层协议是一系列网络应用的前提和基础。然而随着网络的高速化和协议的复杂化&#xff0c;传统的基于端 口识别应用层协议的算法已经不够准确&#xff0c;因此各种新的协议识别算法成为研究热点 。 本篇文章将重点介绍协议识别问题的几个…...

xlsx包安装时Java环境配置

安装xlsx包的Java环境配置 xlsx包安装时&#xff0c;要求必须先装好rJava包&#xff0c;而rJava包安装后&#xff0c;载入rJava包时出现以下错误&#xff1a; JAVA_HOME cannot be determined from the Registry 出现此错误的原因&#xff1a;电脑没有安装Java 解决方法&am…...

R语言数据格式 长数据 和 宽数据 之间的转换

R语言数据格式 长数据 和 宽数据 之间的转换 1.什么是长数据&#xff1f; 2.什么是宽数据&#xff1f; 3.为什么需要转换&#xff1f; 4.转换的方法 1&#xff09;需要用到的R包2&#xff09;函数介绍什么是长数据&#xff1f; 长数据一般是指数据集中的变量没有做明确的细…...

R如何导入带有分隔符号的文件

read.table(file,options) TablesAreCoolcol 3 isright-aligned$1600col 2 iscentered$12zebra stripesare neat$1 options描述header文件第一行是否表明了变量名的逻辑值sep文件中分开数据值的分隔符&#xff0c;默认” “,换行符为“\t”row.names用于指定行标记符的可选参…...

Hadoop回收站trash

Hadoop回收站trash&#xff0c;默认是关闭的。 1.修改conf/core-site.xml,增加 Xml代码 <property> <name>fs.trash.interval</name> <value>1440</value> <description>Number of minutes between trash checkpoints. …...

Pig 安装

Pig 的安装 1.下载文件 在官方上下载下来 http://pig.apache.org/releases.html#Download 我个人下载的 版本是pig-0.11.0.tar.gz 2.安装 上传到服务器指定位置 由于我个人是新创建了一个pig用户来创建的&#xff0c;所以上传到了 /home/pig/这个目录 &#xff08;用…...

pig入门学习

个人目前理解pig是对mapreduce的一种封装扩展&#xff0c;使写mapreduce简单化&#xff0c;可维护性更高一点&#xff0c;可透明性更清晰一点&#xff0c;操作数据更简单一点吧。 1. Pig中的模式 pig中模式就是说pig数据的数据格式是什么样的。 比如当执行 grunt> de…...

Linux Vim使用

高级一些的编辑器&#xff0c;都会包含宏功能&#xff0c;vim当然不能缺少了&#xff0c;在vim中使用宏是非常方便的&#xff1a; :qx 开始记录宏&#xff0c;并将结果存入寄存器xq 退出记录模式x 播放记录在x寄存器中的宏命令稍微解释一下&#xff0c;当在normal模…...

pig 指定行分割符和列分隔符号

由于我们的hdfs上抽取的数据是存储行分隔符和列分割符不是用的\n和\t。所以就想能看看是否能指定行分隔符&#xff0c;查了半天没查到。。可能是查找能力有限&#xff0c;呵呵&#xff0c;后来下载下来pig-0.11.0的源码看了一下PigStorage的类&#xff0c;输入inputFormat类指定…...

pig基础实例运算

基础运算 加减乘除&#xff08; 、-、*、/、bincond &#xff09; 查看一下简单的文本内容 grunt> cat A; 0,1,2 1,3,4 grunt> a load A usingPigStorage(,)as(c1:int,c2:double,c3:float); grunt> b foreach a generate $0$1 asc1_c2; grunt>dump b; (…...

修改linux 系统编码为utf-8

vi /etc/sysconfig/i18n LANG"zh_CN.GBK" 修改为LANG"zh_CN.UTF-8".保存退出source /etc/sysconfig/i18n 检查编码&#xff1a;locale...