65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Python、Flask 和 PostgreSQL 创建一个简单的 Web 应用程序并进行 Docker 化

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2018 年 8 月 21 日

CPOL

13分钟阅读

viewsIcon

23797

downloadIcon

213

使用 Flask 和 PostgreSQL 服务器创建一个 Python Web 应用程序,并在 Docker 中运行它

注意:您可以访问 http://ec2-18-191-184-232.us-east-2.compute.amazonaws.com/ 来评估本文讨论的现成 Web 应用程序。

引言

在本文中,我们将演示如何使用 Docker 帮助我们使用 Python 编程语言和 Flask 开发框架创建和部署一个简单的 Web 应用程序。本文将讨论的应用程序将执行存储在 PostgreSQL 服务器数据库中的数据的简单可视化。特别是,我们将创建一个应用程序,用于通过部分匹配来索引搜索人员及其电话号码的特定数据,这些数据存储在 phonebook 数据库中。要创建以下应用程序,我们将使用 Microsoft Visual Studio 2017 Python 开发工具。之后,我们将通过在 Docker 的虚拟环境中运行来“Docker 化”上述 Web 应用程序。

在本文中,我们将提供有用的指南来设置和配置 Docker 的虚拟化平台,然后使用它来部署各种业务关键型应用程序,为大量 Web 用户提供服务。特别是,本文的读者将具体了解如何部署一个已创建的 Web 应用程序,并在 Docker 的虚拟化平台环境中运行它。

什么是 Docker…

Docker 是一个面向 SaaS 的操作系统级虚拟化平台,它允许快速轻松地创建和部署各种业务 Web 应用程序,而无需深入了解虚拟化技术(VT)或具备大量云服务(CS)部署经验。根据其架构,Docker 的虚拟化平台允许将各种应用程序部署和使用为独立的“容器”,这些容器运行在 Microsoft Hyper-V 硬件虚拟化平台内的单个 MobyLinuxVM 虚拟机实例下。

使用容器(例如,“容器化”)的主要思想是,在 Docker 的虚拟环境中部署的每个服务或应用程序都在其自己的容器中独立运行。

“容器”实际上是一个最小化的虚拟机,托管 Windows 或 Linux 操作系统,通常用于部署特定应用程序或网络服务,例如 HTTP、FTP、NTP、DNS、数据库等。反过来,Docker 的基础设施提供了用于创建运行特定服务或应用程序的容器的存储库,这些容器从模板创建,从而可以更快、更轻松地部署这些服务和应用程序。使用容器模板可以确保我们部署的虚拟机主机已经运行了特定的应用程序或服务,而无需花费时间完成基础结构特定的维护任务,例如安装主机操作系统、设置和配置应用程序或服务守护程序、创建虚拟网络、监控性能等。这使得从“零开始”部署各种基本甚至更高级的服务和应用程序变得简单便捷。

正如我们已经讨论过的,通过使用 Docker 的虚拟化平台,与其他基于 IaaS 的云服务和平台(如 Amazon EC2、Microsoft Azure 或 OpenStack)不同,开发人员不再需要负责完成 IaaS 特定的应用程序维护任务。换句话说,整个基础设施特定的配置过程非常简单,因为它被 Docker 的虚拟化平台封装了。具体来说,Docker 环境中的每个容器都连接到一个网络,提供了 Docker 环境中托管和运行的容器之间的通信。例如,用 Python 编写并在其自己的容器中运行的业务应用程序可以通过 Docker 的预配置虚拟网络访问运行在另一个容器中的 PostgreSQL 服务器数据库实例中的数据。此外,在创建 Docker 容器时,我们不再需要执行每个容器的初始配置,例如设置正在创建的虚拟机的虚拟系统内存量、CPU 数量、虚拟网络适配器配置等。

具体来说,在本文中,我们将学习如何

  • 在主机上安装和配置 Docker 虚拟化平台
  • 通过创建单独的 Docker 容器,将本文介绍的现有 Python Web 应用程序迁移到 Docker 虚拟化环境
  • 从特定模板部署其他服务,例如 PostgreSQL 服务器实例到 Docker
  • 构建创建的 Web 应用程序并将其作为 Docker 的后台服务分离运行

最后,我们将学习如何在 Amazon EC2 云中部署由 Amazon Linux AMI 虚拟机实例托管的 Docker 虚拟化平台环境,以公开访问创建的 Web 应用程序。

背景

在本节中,我们将详细讨论 Docker 化本文介绍的索引搜索 Web 应用程序的过程。

安装和配置 Docker 虚拟化平台

在将 Web 应用程序部署到 Docker 之前,我们要做的第一件事就是安装和配置 Docker 虚拟化平台。在本文中,我们将利用 Amazon EC2 云服务的功能,在由 Amazon Linux AMI 虚拟机托管的环境中安装和运行 Docker。

为此,我们必须创建一个 Amazon EC2 帐户并登录,以创建 Amazon Linux AMI 虚拟机实例,如下图所示

在这些步骤中,我们必须创建 **Amazon EC2** 帐户,登录 **AWS 管理控制台**,并启动 **Amazon Linux AMI** 实例。要创建 Amazon Linux AMI 实例,我们必须确保我们通过以下步骤

步骤 1:选择 Amazon 虚拟机映像

步骤 2:选择实例类型并启动实例

步骤 3:创建 RSA 密钥对,以建立与运行实例的安全 SSH 连接

步骤 3:启动已配置的 Amazon Linux 实例

步骤 4:配置运行中的 Amazon Linux 实例安全组

为了确保我们部署的 Web 应用程序能够通过侦听特定 TCP 端口来接受流量,我们必须正确配置安全组,向以下安全组添加特定的入站规则(例如,HTTP-80 端口),如下图所示

步骤 5:使用 PuTTY 终端应用程序连接到正在运行的 Amazon Linux 实例

正如您在上图所示,Amazon Linux AMI 的运行实例已成功创建,并已生成公共 DNS (IPv4) 主机名。稍后,我们将使用此主机名通过 PuTTY 终端应用程序连接到运行实例的 SSH 控制台。

为此,我们必须下载并安装 PuTTY,并从实例配置阶段先前创建的 *.pem 密钥对文件生成一个特定的 *.ppk 文件。

为此,我们将使用 PuTTYGen 工具,如下图所示

在创建并保存了新的密钥对 *.ppk 文件后,现在让我们使用 PuTTY 终端第一次连接到正在运行的 Amazon Linux 实例控制台,如下所示

要连接到正在运行的 Amazon Linux 实例,我们将使用以下凭据,例如:主机名:ec2-18-191-184-232.us-east-2.compute.amazonaws.com,以及先前生成的 *.ppk 密钥文件。

步骤 6:安装和配置 Docker

既然我们已经启动并配置了 Amazon Linux AMI 虚拟机并连接到其 SSH 控制台,下一步就是在正在运行的 Amazon Linux 实例上部署 Docker 的虚拟化平台。要做到这一点,我们需要在 SSH 控制台中使用以下命令。

在我们开始之前,请确保我们已作为超级用户或 root 登录到 SSH 控制台。要启用 root 帐户,我们必须使用 sudo passwd root 等命令并输入 root 密码。之后,通过输入以下简短命令:su,以“root”身份登录控制台。

要安装 Docker,我们必须输入以下一系列命令

[root@ip-172-31-20-4 ec2-user]# yum update -y

[root@ip-172-31-20-4 ec2-user]# yum install -y docker

整个 Docker 安装过程在下图中有说明

成功安装 Docker 后,我们需要确保它将在下次启动时作为服务运行。为此,我们需要输入以下命令

[root@ip-172-31-20-4 ec2-user]# chkconfig docker on

[root@ip-172-31-20-4 ec2-user]# service docker start

之后,我们必须重启我们的 Amazon Linux AMI 实例,以确保 Docker 在下次启动时自动运行。要执行此操作,只需键入:shutdown -r now.

最后,我们必须确保 Docker 虚拟化环境工作正常。为此,我们必须从存储库运行一个 hello-world Docker 应用程序。

[root@ip-172-31-20-4 ec2-user]# docker run hello-world

步骤 7:创建 PostgreSQL 服务容器

要部署我们的 Web 应用程序,我们必须做的第一件事就是从模板创建一个预配置的 PostgreSQL 服务器实例的 Docker 容器。为此,我们必须执行以下步骤:输入以下命令创建 PostgreSQL 数据存储容器

docker create -v /var/lib/postgresql/data --name PostgresData alpine 

接下来,我们必须创建一个预配置的 PostgreSQL 服务器容器

docker run -d -p 5432:5432 --restart=always --name postgresql_ec2 
           -e POSTGRES_PASSWORD=12345 -d postgres

另外,我们可以通过执行以下命令为正在运行的 PostgreSQL 容器分配一个静态 IP 地址。

要创建自定义 Docker 虚拟网络,请输入以下命令

docker network create --driver=bridge --subnet=178.17.0.0/24 
                      --gateway=178.17.0.1 postgresql_ec2_nw

要运行自定义虚拟网络中的 PostgreSQL 容器,请使用以下命令

docker run -d -p 5432:5432 --name postgresql -it  --network=postgresql_ec2_nw 
--ip=178.17.0.2 --restart always --publish 5432:5432 
--volume /srv/docker/postgresql:/var/lib/postgresql \ 
--env 'PG_TRUST_LOCALNET=true'  --env 'PG_PASSWORD=12345' 
--env 'DB_USER=postgres' --env 'DB_PASS=12345' --env 'DB_NAME=phonebook' postgres

最后,为了确保 PostgreSQL 容器正在运行,让我们输入以下命令

docker ps -a

步骤 8:Phonebook PostgreSQL 数据库维护步骤

在成功设置 PostgreSQL 数据库服务器容器后,我们必须将现成的数据库导入 PostgreSQL 服务器。为此,我们必须在正在运行的 Amazon Linux 实例上额外安装 vsftpd ftp 服务器。安装 ftp 服务器后,我们必须将下图所示的文件复制到我们的 Amazon Linux 实例的 /home/ec2-user 目录。

之后,我们必须将 phone_book.sql 文件复制到 PostgreSQL 容器。为此,我们必须使用以下命令

docker cp ./phone_book.sql postgresql_ec2:/home/phone_book.sql

在成功将上述文件复制到 PostgreSQL 容器后,我们必须将此转储导入数据库服务器并创建 phonebook 数据库及数据。为此,我们必须使用以下命令登录容器控制台

docker exec -it postgresql_ec2 /bin/bash

要导入现有数据库,我们必须输入以下两个命令

psql -U postgres

然后键入 CREATE DATABASE phonebook;sql 语句,之后将创建新的 phonebook 数据库。

psql -U postgres -f /home/phone_book.sql phonebook

输入此命令后,phone_book.sql 转储文件将成功导入新创建的 phonebook 数据库。

步骤 9:构建和运行索引搜索 Web 应用程序

在成功维护 PostgreSQL 数据库服务器并导入包含数据的 phonebook 数据库后,现在让我们构建和部署我们的索引搜索 Web 应用程序。首先,我们必须创建一个适当的 Docker 文件,如下所示

FROM python:3

WORKDIR /eg_phonebook

ADD . /eg_phonebook

RUN pip install --trusted-host pypi.python.org -r requirements.txt 
RUN pip install pystrich psycopg2-binary requests

EXPOSE 80

CMD [ "python", "./eg_phonebook.py" ]

在此文件中,我们必须指定要从中下载和导入 Python 包的存储库(例如,FROM python:3)。此外,我们必须提供应用程序的工作目录(例如,WORKDIR /eg_phonebook)和 Python 主应用程序的文件名(ADD . /eg_phonebook)。此外,我们将使用 RUN 包装器命令来执行 Python 的 pip 工具,该工具允许我们下载和安装额外的 Python 模块。

RUN pip install --trusted-host pypi.python.org -r requirements.txt

RUN pip install pystrich psycopg2-binary requests

最后,我们必须提供 eg_phonebook 应用程序将侦听的 TCP 端口。在 Docker 文件底部,我们必须执行 CMD 命令,该命令用于通过构建特定的主应用程序文件来构建我们的 Python Web 应用程序(例如,CMD [ "python", "./eg_phonebook.py" ])。

最后,在创建了 Docker 文件后,我们必须输入以下命令来构建我们的 eg_phonebook Web 应用程序。

docker build -t eg_phonebook .

要运行该应用程序,我们将使用以下命令

docker run -d -p 80:80 --restart=always eg_phonebook

执行此命令后,以下 Web 应用程序将作为服务在后台运行,并侦听 TCP 端口 80。

可选地,我们可以使用以下命令停止和移除正在运行的容器

docker stop <container-id>

docker rm <container-id>

为了验证应用程序是否正常工作,让我们转到 Web 浏览器并输入以下 URL 地址

http://ec2-18-191-184-232.us-east-2.compute.amazonaws.com:80/

正如您在上图所示,以下 Web 应用程序已启动并准备就绪。

Using the Code

作为部署到 Docker 虚拟化环境中运行的 Web 应用程序的一个例子,我们创建了一个应用程序,该应用程序通过部分匹配执行索引搜索存储在 PostgreSQL 数据库中的人员和电话号码数据。该应用程序旨在可视化显示在 Web 应用程序主页面中呈现的表格中的搜索结果。

应用程序的主 Web 页面 HTML 文档如下所示。该 HTML 文档呈现了一个人员和电话号码的表格,该表格精确或部分匹配搜索模式,并由应用程序的主 Python 脚本动态构建。该 HTML 文档包含一段 JavaScript 代码,该代码执行 HTTP Ajax 请求到应用程序的 Web 服务器,并根据应用程序的主 Python 脚本执行的查询事务从 PostgreSQL 服务器数据库检索人员和电话号码的数据。响应通常包含组织成 HTML 表格的数据,然后该表格动态地嵌入并呈现为应用程序主 Web 页面的一个部分。具体来说,在 JavaScript 代码片段中,我们在 doSearch() 方法中定义了该方法,在该方法中我们通过创建 XMLHttpRequest() 对象并定义回调函数来处理 onreadystatechange 事件,该事件在请求完成后触发。在此函数内部,我们获取 Ajax 请求的响应文本,并在请求处理后,将应用程序的 Python 脚本返回的 HTML 表格嵌入到应用程序的主 Web 页面中。为了发送 Ajax 请求,我们通常构造一个 URL 字符串,该字符串由应用程序 Web 服务器地址和一系列 URL 参数组成,例如 /search?text=query_string。特别是 query_string 值是通过使用 document.getElementById("query").value 属性从可编辑文本字段中检索的。构造 URL 字符串后,我们将调用 XMLHttpRequest().open 方法,并将构造的字符串作为此方法的参数之一传递。

doSearch 方法通常作为 HTML 文档用户输入控件触发的 onloadonkeyuponclick 事件的结果而被调用。例如,如果用户开始输入查询 string,则会触发 onkeyup 事件并由 doSeach 函数处理,该函数从可编辑文本字段获取 string 值,并向正在执行的 Web 应用程序的主 Python 脚本发送 Ajax 请求。

index.html

<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <script type="text/javascript">
    function doSearch() { 
      var xhttp = new XMLHttpRequest(); 
      xhttp.onreadystatechange = function() { 
        if (this.readyState == 4 && this.status == 200) { 
           document.getElementById("result").innerHTML = xhttp.responseText; 
        } 
      };
     
      xhttp.open("GET", "/search?text=" + document.getElementById("query").value, true); 
      xhttp.send(); 
    } 
  </script>
 </head>
 <body onload="doSearch();">         
   <table border="0">
    <tbody>
     <tr><td align="center"><b>Docker's Indexed Search App v.1.00a</b></td></tr>
     <tr>
      <td>
       <table border="0">
        <tbody>
         <tr>
          <td>Search:</td>
          <td><input id="query" type="text" onkeyup="doSearch();" 
               onpaste="doSearch();"></td>
          <td><input type="submit" onclick="doSearch();"></td> 
         </tr>
        </tbody>
       </table> 
      </td>
     </tr>
     <tr><td><center><p id="result"></p></center></td></tr>
    </tbody>
   </table>
 </body>
</html>

应用程序的主 Python 脚本在嵌入到应用程序主 Web 页面的 HTTP 文档中的特定 JavaScript 代码每次发送 HTTP Ajax 请求时都会执行。在执行以下 Python 脚本时,我们将实例化 Flask 和 Redis 对象,并分派 app.run(HOST, PORT) 方法在服务器端启动 Web 应用程序。在执行以下脚本时,我们将执行基于所发送 HTTP 请求的路由。特别是,在处理默认路由时,我们将上面显示的 HTML 文档构造为一个由 main_empty 函数返回的 string 缓冲区。否则,对于 /search?text=query_string 路由,我们将建立与 PostgreSQL 数据库服务器的连接,构造并执行查询的 SQL 语句,例如 SELECT person_id, person_name, phone FROM public.persons WHERE \ person_name ILIKE '%""" + search_pattern + """%' OR phone ILIKE '%""" + search_pattern + """%',其执行结果是获取一组与给定搜索模式精确或部分匹配的行。如果 URL 字符串的 text 参数值为空,那么我们将执行另一个 SQL 语句,该语句返回 persons 表中的所有行的集合。

在执行 SQL 语句后,我们将获取结果行集并生成一个 HTML 表格,其中每一行包含匹配搜索模式的每个特定人员和电话号码的数据。生成的 HTML 内容存储在 string 缓冲区中,该缓冲区将进一步作为对正在处理的 Ajax 请求的响应返回。

eg_phonebook.py

"""
This script runs the application using a development server.
It contains the definition of routes and views for the application.
"""

# Importing Flask from flask repository
from flask import Flask
# Importing redis from Redis and RedisError repositories
from redis import Redis, RedisError
# Importing HTTP-requests object from flask repository
from flask import request
# Importing os and socket objects from Python:3.0 repository
import os
import socket
# Importing PostgreSQL client adapter object from Python:3.0 repository
import psycopg2;

# Creating redis data store object
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
# Creating Flask web application framework object
app = Flask(__name__)

# Make the WSGI interface available at the top level so wfastcgi can get it.
wsgi_app = app.wsgi_app

# Performing default routing
@app.route('/')
def main_empty():
    # Returning string buffer containing the applications web-page being generated
    return "<html><head><script type=\"text/javascript\">function doSearch() \
    { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() \
        { if (this.readyState == 4 && this.status == 200) \
        { document.getElementById(\"result\").innerHTML = xhttp.responseText; } }; \
        xhttp.open(\"GET\", \"/search?text=\" + 
        document.getElementById(\"query\").value, true); \
        xhttp.send(); } </script></head><body onload=\"doSearch();\"> \
        <table border=\"0\"><tr><td align=\"center\"><b>Docker\'s \
        Indexed Search App v.1.00a</b></td></tr><tr><td><table border=\"0\">\
        <tr><td>Search:</td><td> \
        <input id=\"query\" type=\"text\" onkeyup=\"doSearch();\" 
        onpaste=\"doSearch();\"></td>\
        <td><input type=\"submit\" onclick=\"doSearch();\"></td></tr></table> \
        </tr><tr><td><center><p id=\"result\">&nbsp;</p></center>\
        </td></tr></table></body></html>";

# Performing /search routing
@app.route('/search')
def search():
    # Getting value of the /search?text=query_string URL-parameter
    search_pattern = request.args.get("text");

    # Connecting to PostgreSQL database server by using PostgreSQL 
    # Python client adapter object
    conn=psycopg2.connect(database="phonebook", user="postgres", \
                          host="172.17.0.2", password="12345")

    # Getting the initial value of database connection curson
    cursor = conn.cursor()

    pg_query_string = "\0";
    # Performing a check if the search pattern 
    # /search?text=query_string is not equal to an empty string
    if search_pattern != "\0":
        # If not, construct a query string based on SQL statement 
        # performing the conditional query to get a resulting set of rows 
        # that exactly or partially match the given condition
        pg_query_string = """SELECT person_id, person_name, phone \
            FROM public.persons WHERE \
            person_name ILIKE '%""" + search_pattern + """%' \
            OR phone ILIKE '%""" + search_pattern + """%';"""
    # If yes, construct a query string based on SQL statement, 
    # fetching all rows from public.person table
    else: pg_query_string = """SELECT person_id, person_name, \
          phone FROM public.persons;""";

    # Executing SQL statement contained in query_string buffer using curson object
    cursor.execute(pg_query_string)

    # Generating html table and its header as the contents of html string buffer
    html = "<table border=\"0\">";
    html += "<tr><th>#</th><th>Person Name</th><th>Phone</th></tr>"

    # Assigning the initial value of row_id counter variable to 0
    row_id = 0
    # Fetching all rows from the query resultant set and assign the 
    # array of rows to rows variable
    rows = cursor.fetchall()
    # Iterating through the array of rows
    for row in rows:
        # For each row, generating html table row with column values 
        # obtained from the SQL query resultant set
        # Performing a check if the current row_id value is odd (e.g. row_id % 2 != 0)
        # If so, set table row's background style color to `light-grey', 
        # otherwise using `white` color
        html += "<tr style=\"background-color:" + \
            ("#eee" if (row_id % 2) != 0 else "#fff") + "\">";
        html += "<td>" + str(row[0]) + "</td>";
        html += "<td>" + row[1]      + "</td>";
        html += "<td>" + row[2]      + "</td></tr>";
        # Incrementing the value of row_id counter variable
        row_id = row_id + 1;

    # Generating the html table closing tag
    html += "</table>";

    # Returning the html document containing the search results html table
    return html;

if __name__ == '__main__':
    import os
    # Getting the value of hostname (e.g. 0.0.0.0) from the environment
    HOST = os.environ.get('SERVER_HOST', '0.0.0.0')
    try:
        # Getting the value of app's TCP-port equal to 80 from the environment
        PORT = int(os.environ.get('SERVER_PORT', '80'))
    except ValueError:
        PORT = 5555
    # Launching the web-application
    app.run(HOST, PORT)

phonebook”是一个小型数据库,只包含一个名为 'persons' 的表,该表有两个类型为 'text' 的字段,分别是 'person_name''phone'。下面列出了包括约束和数据的 'phonebook' 数据库的 SQL 转储。

phone_book.sql

--
-- PostgreSQL database dump
--

-- Dumped from database version 10.5
-- Dumped by pg_dump version 10.4

-- Started on 2018-08-18 14:20:06

SET statement_timeout = 0;

SET lock_timeout = 0;

SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';

SET standard_conforming_strings = on;

SELECT pg_catalog.set_config('search_path', '', false);

SET check_function_bodies = false;

SET client_min_messages = warning;

SET row_security = off;

DROP DATABASE "phonebook";

--
-- TOC entry 2156 (class 1262 OID 16432)
-- Name: phonebook; Type: DATABASE; Schema: -; Owner: -
--

CREATE DATABASE "phonebook" WITH TEMPLATE = template0 ENCODING = 'UTF8' _
LC_COLLATE = 'Ukrainian_Ukraine.1251' LC_CTYPE = 'Ukrainian_Ukraine.1251';

\connect "phonebook"

SET statement_timeout = 0;

SET lock_timeout = 0;

SET idle_in_transaction_session_timeout = 0;

SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;

SELECT pg_catalog.set_config('search_path', '', false);

SET check_function_bodies = false;

SET client_min_messages = warning;

SET row_security = off;

--
-- TOC entry 2157 (class 0 OID 0)
-- Dependencies: 5
-- Name: SCHEMA "public"; Type: COMMENT; Schema: -; Owner: -
--

COMMENT ON SCHEMA "public" IS 'standard public schema';

--
-- TOC entry 1 (class 3079 OID 12278)
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS "plpgsql" WITH SCHEMA "pg_catalog";

--
-- TOC entry 2158 (class 0 OID 0)
-- Dependencies: 1
-- Name: EXTENSION "plpgsql"; Type: COMMENT; Schema: -; Owner: -
--

COMMENT ON EXTENSION "plpgsql" IS 'PL/pgSQL procedural language';

--
-- TOC entry 197 (class 1259 OID 16444)
-- Name: person_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE "public"."person_id_seq"
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

SET default_with_oids = false;

--
-- TOC entry 196 (class 1259 OID 16436)

-- Name: persons; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE "public"."persons" (
    "person_id" integer DEFAULT _
    "nextval"('"public"."person_id_seq"'::"regclass") NOT NULL,
    "person_name" "text",
    "phone" "text"
);

--
-- TOC entry 2149 (class 0 OID 16436)
-- Dependencies: 196
-- Data for Name: persons; Type: TABLE DATA; Schema: public; Owner: -
--

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (1, 'John W. Smith', '+1(719)444-5555');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (2, 'Richard Stone', '+1(614)333-2211');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (3, 'Jeffry Wilkins', '+1(212)818-2236');
INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (4, 'William Travis', '+1(453)545-0390');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (5, 'Tony Creek', '+1(451)452-3311');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (6, 'Ronald Steward', '+1(718)959-4310');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (7, 'Collin Whitney', '+1(410)541-3456');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (8, 'Steven Cromb', '+1(461)553-4312');

INSERT INTO "public"."persons" ("person_id", "person_name", "phone") _
VALUES (9, 'Dave Blackstock', '+1(466)443-2228');

--
-- TOC entry 2159 (class 0 OID 0)

-- Dependencies: 197
-- Name: person_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--
SELECT pg_catalog.setval('"public"."person_id_seq"', 9, true);

--
-- TOC entry 2027 (class 2606 OID 16443)
-- Name: persons person_id_pk; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY "public"."persons"
    ADD CONSTRAINT "person_id_pk" PRIMARY KEY ("person_id");

-- Completed on 2018-08-18 14:20:07

--
-- PostgreSQL database dump complete
--

关注点

在本文中,我们讨论了一种创建和 Docker 化简单 Web 应用程序的方法,该方法还可以用于部署本文介绍以外的其他应用程序。

历史

  • 2018 年 8 月 21 日 - 文章初稿发布
© . All rights reserved.