{"id":234,"date":"2018-09-28T12:00:46","date_gmt":"2018-09-28T04:00:46","guid":{"rendered":"http:\/\/www.yinyubo.cn\/?p=234"},"modified":"2022-05-17T09:50:16","modified_gmt":"2022-05-17T01:50:16","slug":"dockerfile-python","status":"publish","type":"post","link":"https:\/\/www.yinyubo.com\/?p=234","title":{"rendered":"docker\u5b98\u7f51\u5b9e\u4f8b\uff0c\u7528Dockerfile\u6784\u5efa\u4f60\u7684\u7b2c\u4e00\u4e2apython\u5e94\u7528"},"content":{"rendered":"<p>#\u5907\u6ce8\uff1a\u9ed8\u8ba4\u8bfb\u8005\u5df2\u7ecf\u5b89\u88c5\u597d\u4e86docker\u73af\u5883<\/p>\n<h4><strong>\u7b2c\u4e00\u6b65\uff1a\u521b\u5efa\u4e00\u4e2a\u5e94\u7528\u76ee\u5f55(\u540e\u9762\u4f7f\u7528\u8be5\u76ee\u5f55\u4e3a\u5de5\u4f5c\u76ee\u5f55\uff0c\u5b58\u653e\u5e94\u7528\u6587\u4ef6\u4ee5\u53caDockerfile)\uff1a<\/strong><\/h4>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">mkdir \/root\/docker\/lzwtestpython\ncd \/root\/docker\/lzwtestpython<\/code><\/pre>\n<h4>\u7b2c\u4e8c\u6b65\uff1a\u4e3a\u5bb9\u5668\u5b9a\u4e49\u4e00\u4e2a<strong>Dockerfile\uff1a<\/strong><\/h4>\n<p>\u521b\u5efaDockerfile\u6587\u4ef6\uff1a<\/p>\n<pre class=\"lang:python decode:true\">vi Dockerfile<\/pre>\n<p>\u8f93\u5165Dockerfile\u6587\u4ef6\u5185\u5bb9\uff1a<\/p>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\"># Use an official Python runtime as a parent image\nFROM python:2.7-slim\n# Set the working directory to \/app\nWORKDIR \/app\n# Copy the current directory contents into the container at \/app\nCOPY . \/app\n# Install any needed packages specified in requirements.txt\nRUN pip install --trusted-host pypi.python.org -r requirements.txt\n# Make port 80 available to the world outside this container\nEXPOSE 80\n# Define environment variable\nENV NAME World\n# Run app.py when the container launches\nCMD [\"python\", \"app.py\"]<\/code><\/pre>\n<p>\u5728\u6587\u4ef6\u5185\u5bb9\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\uff0c\u6211\u4eec\u7684python\u6587\u4ef6\u4e3aapp.py\uff0c\u4e0b\u9762\u6211\u4eec\u9700\u8981\u53bb\u521b\u5efa\u8fd9\u4e2a\u6587\u4ef6\u3002\u4e00\u822c\u6765\u8bf4,python\u9879\u76ee\u4e2d\u4f1a\u5305\u542b\u4e00\u4e2a\u00a0requirements.txt\u00a0\u6587\u4ef6,\u7528\u4e8e\u8bb0\u5f55\u6240\u6709\u4f9d\u8d56\u5305\u3002<\/p>\n<h4>\u7b2c\u4e09\u6b65\uff1a\u521b\u5efarequirements.txt\u548capp.py<\/h4>\n<p>\u521b\u5efarequirements.txt\u6587\u4ef6\uff1a<\/p>\n<pre class=\"lang:python decode:true \">vi requirements.txt<\/pre>\n<p>\u8f93\u5165requirements.txt\u6587\u4ef6\u5185\u5bb9\uff1a<\/p>\n<pre class=\"highlight\"><code>Flask\nRedis<\/code><\/pre>\n<div class=\"language-python highlighter-rouge\">\n<div class=\"highlight\">\u521b\u5efaapp.py\u6587\u4ef6\uff1a<\/div>\n<div>\n<pre class=\"lang:python decode:true \">vi app.py<\/pre>\n<p>\u8f93\u5165app.py\u6587\u4ef6\u5185\u5bb9\uff1a<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"golang\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">from flask import Flask\nfrom redis import Redis, RedisError\nimport os\nimport socket\n# Connect to Redis\nredis = Redis(host=\"redis\", db=0, socket_connect_timeout=2, socket_timeout=2)\napp = Flask(__name__)\n@app.route(\"\/\")\ndef hello():\n    try:\n        visits = redis.incr(\"counter\")\n    except RedisError:\n        visits = \"&lt;i&gt;cannot connect to Redis, counter disabled&lt;\/i&gt;\"\n    html = \"&lt;h3&gt;Hello {name}!&lt;\/h3&gt;\" \\\n           \"&lt;b&gt;Hostname:&lt;\/b&gt; {hostname}&lt;br\/&gt;\" \\\n           \"&lt;b&gt;Visits:&lt;\/b&gt; {visits}\"\n    return html.format(name=os.getenv(\"NAME\", \"world\"), hostname=socket.gethostname(), visits=visits)\nif __name__ == \"__main__\":\n    app.run(host='0.0.0.0', port=80)<\/code><\/pre>\n<p>\u5230\u8fd9\u91cc\uff0c\u6211\u4eec\u53ef\u4ee5\u53d1\u73b0\uff0c\u6211\u4eec\u6ca1\u6709\u771f\u6b63\u7684\u5728\u7535\u8111\u4e0a\u5b89\u88c5python,\u548crequirements.txt\u91cc\u63d0\u5230\u7684flask\u6216\u8005redis\u3002\u770b\u8d77\u6765\uff0c\u4f60\u5e76\u6ca1\u6709\u642d\u5efa\u597dpython+flask+redis\u7684\u73af\u5883\u3002\u4f46\u662f\uff0c\u901a\u8fc7\u63a5\u4e0b\u6765\u7684\u6b65\u9aa4\uff0c\u4f60\u5373\u5c06\u62e5\u6709\u3002<\/p>\n<h4>\u7b2c\u56db\u6b65\uff1a\u521b\u5efa\u5e94\u7528<\/h4>\n<p>\u68c0\u67e5\u5de5\u4f5c\u6587\u4ef6\u5939\u4e0b\u7684\u4e09\u4e2a\u6587\u4ef6\u662f\u5426\u90fd\u521b\u5efa\u5b8c\u6210\uff0c\u4e09\u4e2a\u6587\u4ef6\u5982\u4e0b\uff1a<\/p>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">$ ls\nDockerfile\t\tapp.py\t\t\trequirements.txt<\/code><\/pre>\n<p>\u73b0\u5728\u5f00\u59cb\u8fd0\u884c\u521b\u5efaDocker\u955c\u50cf\u547d\u4ee4\uff0c\u6211\u4eec\u52a0\u4e0a-t\u547d\u4ee4\u6765\u547d\u540d\uff0c\u8fd9\u91cc\u6211\u4eec\u8d77\u4e00\u4e2a\u5f88\u53cb\u597d\u7684\u540d\u5b57friendlyhello\uff08^_^\uff09<\/p>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">docker build -t friendlyhello .<\/code><\/pre>\n<p>\u6211\u4eec\u53ef\u4ee5\u770b\u4e00\u770b\u6267\u884c\u7684\u547d\u4ee4\u7684\u56de\u663e\uff1a<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"golang\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">Sending build context to Docker daemon  4.608kB\nStep 1\/7 : FROM python:2.7-slim\n2.7-slim: Pulling from library\/python\n802b00ed6f79: Pull complete\n10b2d5f7ed73: Pull complete\n1073a127cf89: Pull complete\n90283f3dc1cd: Pull complete\nDigest: sha256:0a43a6d7858af4a42427c792b682936d2cd34e183fb026627f53ddb556d4bf62\nStatus: Downloaded newer image for python:2.7-slim\n ---&gt; c9cde4658340\nStep 2\/7 : WORKDIR \/app\n ---&gt; Running in 5b6e0800c538\nRemoving intermediate container 5b6e0800c538\n ---&gt; 3ac183b809ce\nStep 3\/7 : COPY . \/app\n ---&gt; b05ac52c77de\nStep 4\/7 : RUN pip install --trusted-host pypi.python.org -r requirements.txt\n ---&gt; Running in 58bd2a10311e\nCollecting Flask (from -r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/7f\/e7\/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b\/Flask-1.0.2-py2.py3-none-any.whl (91kB)\nCollecting Redis (from -r requirements.txt (line 2))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/3b\/f6\/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052\/redis-2.10.6-py2.py3-none-any.whl (64kB)\nCollecting itsdangerous&gt;=0.24 (from Flask-&gt;-r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/dc\/b4\/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4\/itsdangerous-0.24.tar.gz (46kB)\nCollecting Jinja2&gt;=2.10 (from Flask-&gt;-r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/7f\/ff\/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731\/Jinja2-2.10-py2.py3-none-any.whl (126kB)\nCollecting Werkzeug&gt;=0.14 (from Flask-&gt;-r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/20\/c4\/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243\/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)\nCollecting click&gt;=5.1 (from Flask-&gt;-r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/fa\/37\/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec\/Click-7.0-py2.py3-none-any.whl (81kB)\nCollecting MarkupSafe&gt;=0.23 (from Jinja2&gt;=2.10-&gt;Flask-&gt;-r requirements.txt (line 1))\n  Downloading https:\/\/files.pythonhosted.org\/packages\/4d\/de\/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b\/MarkupSafe-1.0.tar.gz\nBuilding wheels for collected packages: itsdangerous, MarkupSafe\n  Running setup.py bdist_wheel for itsdangerous: started\n  Running setup.py bdist_wheel for itsdangerous: finished with status 'done'\n  Stored in directory: \/root\/.cache\/pip\/wheels\/2c\/4a\/61\/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5\n  Running setup.py bdist_wheel for MarkupSafe: started\n  Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'\n  Stored in directory: \/root\/.cache\/pip\/wheels\/33\/56\/20\/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46\nSuccessfully built itsdangerous MarkupSafe\nInstalling collected packages: itsdangerous, MarkupSafe, Jinja2, Werkzeug, click, Flask, Redis\nSuccessfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Redis-2.10.6 Werkzeug-0.14.1 click-7.0 itsdangerous-0.24\nRemoving intermediate container 58bd2a10311e\n ---&gt; 20b7d92b6075\nStep 5\/7 : EXPOSE 80\n ---&gt; Running in 45f7bfcee8c8\nRemoving intermediate container 45f7bfcee8c8\n ---&gt; 0c99f24bb0ca\nStep 6\/7 : ENV NAME World\n ---&gt; Running in 4d192a73ee76\nRemoving intermediate container 4d192a73ee76\n ---&gt; da526dcf3514\nStep 7\/7 : CMD [\"python\", \"app.py\"]\n ---&gt; Running in 50226d88c2d5\nRemoving intermediate container 50226d88c2d5\n ---&gt; bb0d475e1b3c\nSuccessfully built bb0d475e1b3c\nSuccessfully tagged friendlyhello:latest<\/code><\/pre>\n<p>\u5206\u6790\u56de\u663e\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u6267\u884c\u7684\u8fc7\u7a0b\u67097\u6b65\uff1a<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"golang\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">Step 1\/7 : FROM python:2.7-slim\nStep 2\/7 : WORKDIR \/app\nStep 3\/7 : COPY . \/app\nStep 4\/7 : RUN pip install --trusted-host pypi.python.org -r requirements.txt\nStep 5\/7 : EXPOSE 80\nStep 6\/7 : ENV NAME World\nStep 7\/7 : CMD [\"python\", \"app.py\"]<\/code><\/pre>\n<p>\u8fd97\u6b65\uff0c\u662f\u5728Dockerfile\u91cc\u6307\u5b9a\u7684(\u6240\u4ee5Dockerfile\u6700\u5173\u952e\u554a#_#)\u3002<br \/>\n\u547d\u4ee4\u6267\u884c\u5b8c\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u8f93\u5165\u5982\u4e0b\u547d\u4ee4\u6765\u67e5\u770b\u672c\u673a\u5b89\u88c5\u7684docker \u955c\u50cf<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"golang\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">$ docker image ls\nREPOSITORY            TAG                 IMAGE ID\nfriendlyhello         latest              326387cea398\u7b2c\u4e94\u6b65<\/code><\/pre>\n<h4>\u7b2c\u4e94\u6b65\uff1a\u8fd0\u884c\u5e94\u7528<\/h4>\n<p>\u8fd0\u884c\u5e94\u7528\uff0c\u5e76\u4e14\u628a\u4f60\u7269\u7406\u673a\uff08\u6216\u8005\u4e91\u670d\u52a1\u5668\uff09\u76844000\u7aef\u53e3\u6620\u5c04\u5230\u6211\u4eec\u5bb9\u5668\u768480\u7aef\u53e3\uff0c\u4f7f\u7528-p\u547d\u4ee4\uff1a<\/p>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">docker run -p 4000:80 friendlyhello<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u54c8\uff1f\u4f60\u95ee\u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u505a\uff1f\u56e0\u4e3a\u4f60\u7684app.py\u6587\u4ef6\u91cc\u6307\u7684\u662f80\u7aef\u53e3\uff0c\u5982\u679c\u6211\u4eec\u6ca1\u6709\u4f7f\u7528docker,\u76f4\u63a5\u662f\u5728\u81ea\u5df1\u7535\u8111\u4e0a\u8fd0\u884c\u8be5python\u7a0b\u5e8f\uff0c\u786e\u5b9e\u53ef\u4ee5\u901a\u8fc7http:\/\/0.0.0.0:80\u8fdb\u884c\u8bbf\u95ee\u3002\u76ee\u524d\u5728\u6211\u4eec\u7684\u5bb9\u5668\u4e2d\uff0c\u786e\u5b9e\u4e5f\u662f80\u7aef\u53e3\u542f\u7528\u4e86\uff0c\u4f46\u662f\u8981\u8ba9\u6211\u4eec\u7684\u5176\u4ed6\u7528\u6237\u8bbf\u95ee\u8fd9\u53f0\u7269\u7406\u673a\u5730\u5740\u7684\u5bb9\u5668\u5185\u7684python\u5e94\u7528\uff0c\u9700\u8981\u628a\u7269\u7406\u673a\u7684\u7aef\u53e34000\u4e0e\u5bb9\u5668\u768480\u7aef\u53e3\u8fdb\u884c\u6620\u5c04\u3002\u73b0\u5728\uff0c\u8bf7\u7528http:\/\/localhost:4000 \u6765\u68c0\u67e5\u4e00\u4e0b\u5427<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-236 size-full\" src=\"https:\/\/yinyubo-1257235934.cos.ap-nanjing.myqcloud.com\/content\/app-in-browser.png\" alt=\"\" width=\"652\" height=\"313\" \/><br \/>\n\u5982\u679c\u4f60\u662f\u5e03\u7f6e\u5728\u522b\u7684\u673a\u5668\u4e0a\u800c\u975e\u672c\u673a\u7684\u8bdd\uff0c\u4e5f\u53ef\u4ee5\u7528\u5730\u5740\u52a0\u7aef\u53e3\u53f7\u7684\u65b9\u5f0f\u6765\u8bbf\u95ee\u3002\u4f8b\u5982http:\/\/192.168.99.100:4000\/ \u6216\u8005http:\/\/www.yinyubo.cn:4000\/<br \/>\n\u6ca1\u6709\u6d4f\u89c8\u5668\u7684\u8bdd\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7curl\u547d\u4ee4\u5de5\u5177\u6765\u8bbf\u95ee<\/p>\n<pre class=\"lang:python decode:true \"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">$ curl http:\/\/localhost:4000\n&lt;h3&gt;Hello World!&lt;\/h3&gt;&lt;b&gt;Hostname:&lt;\/b&gt; 8fc990912a14&lt;br\/&gt;&lt;b&gt;Visits:&lt;\/b&gt; &lt;i&gt;cannot connect to Redis, counter disabled&lt;\/i&gt;<\/code><\/pre>\n<p>\u5982\u679c\u4f60\u9700\u8981\u5173\u95eddocker\u5e94\u7528\u7684\u8bdd\uff0c\u53ef\u4ee5\u7528\u5982\u4e0b\u65b9\u6cd5\uff1a<\/p>\n<pre class=\"lang:python decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">$ docker container ls\nCONTAINER ID        IMAGE               COMMAND             CREATED\n1fa4ab2cf395        friendlyhello       \"python app.py\"     28 seconds ago<\/code><\/pre>\n<p>\u5148\u83b7\u5f97docker \u5bb9\u5668\u7684ID\uff0c\u7136\u540e\u7528docker container stop \u547d\u4ee4\u6765\u5173\u95ed\u5b83\uff0c\u4f8b\u5982\uff1a<\/p>\n<pre class=\"lang:python decode:true \"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">docker container stop 1fa4ab2cf395<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>#\u5907\u6ce8\uff1a\u9ed8\u8ba4\u8bfb\u8005\u5df2\u7ecf\u5b89\u88c5\u597d\u4e86docker\u73af\u5883 \u7b2c\u4e00\u6b65\uff1a\u521b\u5efa\u4e00\u4e2a\u5e94\u7528\u76ee\u5f55(\u540e\u9762\u4f7f\u7528\u8be5\u76ee\u5f55\u4e3a\u5de5\u4f5c\u76ee\u5f55\uff0c\u5b58\u653e\u5e94\u7528\u6587\u4ef6 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":236,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,5],"tags":[],"class_list":["post-234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-k8s","category-python"],"_links":{"self":[{"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/posts\/234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=234"}],"version-history":[{"count":1,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions"}],"predecessor-version":[{"id":881,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions\/881"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=\/wp\/v2\/media\/236"}],"wp:attachment":[{"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yinyubo.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}