<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on 勇气</title><link>https://courages.us/category/docker/</link><description>Recent content in Docker on 勇气</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 04 Nov 2020 10:59:32 +0800</lastBuildDate><atom:link href="https://courages.us/category/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>API 网关 Kong</title><link>https://courages.us/api-%E7%BD%91%E5%85%B3-kong/</link><pubDate>Wed, 28 Oct 2020 10:35:51 +0800</pubDate><guid>https://courages.us/api-%E7%BD%91%E5%85%B3-kong/</guid><description>&lt;p&gt;从前开发一个互联网服务程序，大概可以在一台机器上完成：数据库、应用都在一起。随着业务发展壮大，会把数据库独立出来，以便扩展拆分。然后再把一部分公用业务独立出来扩展，譬如文件存储、缓存等。接着业务也才拆分，比如会员、商品。微服务大行其道，各个团队维护着许多服务、API。这么多服务，前端业务逻辑该怎么接入呢？&lt;br&gt;&#10;如今单一的前端UI也可能是多个团队共同开发的结果。当你在本地开发一个小功能时，甚至会牵扯到多个前端UI/后端API。一个前端页面除了加载自己的资源外，还加载V2/V3的API（为什么会同时存在V1/V2/V3的API），甚至嵌入了另外一个页面（React看起来也不错），该怎么调试这种混合开发呢？cookie都传递不过去，好吧，使用&lt;a class="link" href="http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html" target="_blank" rel="noopener"&#10; &gt;JWT&lt;/a&gt;代替，再设置一下&lt;a class="link" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS" target="_blank" rel="noopener"&#10; &gt;跨源资源共享（CORS）&lt;/a&gt;。。。但是那些旧的应用怎么办？&lt;br&gt;&#10;当我们启动一个Node.js应用时npm run start，默认监听3000端口。当然我们也可以让它监听80端口。但是当我们多开几个应用时，只好让它们都监听不同端口了，怎么样才能统一端口监听呢？当然Node.js可以通过诸如&lt;a class="link" href="https://github.com/http-party/node-http-proxy" target="_blank" rel="noopener"&#10; &gt;node-http-proxy&lt;/a&gt;来转发这些请求，但是代理转发跟应用业务无关吧？如果是其他编程语言呢？都重复这些代理配置/开发吗？Don’t Repeat Yourself。&lt;br&gt;&#10;&lt;a class="link" href="https://www.redhat.com/zh/topics/cloud-native-apps/what-is-faas" target="_blank" rel="noopener"&#10; &gt;Faas&lt;/a&gt;也日渐流行，比如&lt;a class="link" href="https://aws.amazon.com/lambda/" target="_blank" rel="noopener"&#10; &gt;AWS Lambda&lt;/a&gt;， 强调仅仅专注某个功能，根据事件驱动进行计算，那么每个服务也要开发一整套路由分发/认证/日志吗？&lt;br&gt;&#10;这些问题可以使用反向代理来解决，提供统一的服务入口，对前端/客户端隐藏背后的细节，最简单的当然是Nginx。Nginx监听来自某个端口（比如80）的请求，然后根据不同的来源/端口/域名/url分发给不同的后端服务器。这看起来跟云服务厂商各自开发的负载均衡器差不多，比如&lt;a class="link" href="https://aws.amazon.com/cn/elasticloadbalancing/" target="_blank" rel="noopener"&#10; &gt;AWS ELB&lt;/a&gt;。&lt;br&gt;&#10;在本地开发的时候，我们当然不会使用ELB来解决。直接使用Nginx当然也没啥问题，编辑一下配置文件，重启应用。但是如果有个UI就更好了，如果还有API就非常好了-这样就能方便的在线注册/更改路由而不需要重启服务器，在这个快速发展、弹性开发的年代更需要这个能力。&lt;br&gt;&#10;&lt;a class="link" href="https://konghq.com/kong/" target="_blank" rel="noopener"&#10; &gt;Kong&lt;/a&gt;是一个基于OpenResty的网关服务器，可以进行路由（转发/负载），插件（日志/认证/监控）管理，并提供RESTful API。而&lt;a class="link" href="https://openresty.org/" target="_blank" rel="noopener"&#10; &gt;OpenResty&lt;/a&gt; 是一个基于Nginx与Lua的高性能Web平台，使用Lua来构建动态网关。听起来像是在Nginx上面编程，这跟在Apache上面使用PHP模块进行编程有什么区别？最大的区别在于，这里的编程对象是Nginx（或者公共模块），扩展Nginx能力，比如负载均衡/日志/认证/监控，而不是输出web页面/业务逻辑。这些东西抽出来以后，就不需要每个模块再重复开发了，比如认证/安全。&lt;br&gt;&#10;在本地可以使用docker来运行Kong服务，麻烦在于数据库迁移工作。通常部署Kong需要几个步骤，比如初始化数据库，迁移升级等等。网上的配置大都过时了，这里可以使用官方提供&lt;a class="link" href="https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml" target="_blank" rel="noopener"&#10; &gt;docker-compose.yml&lt;/a&gt;来做数据库工作，并且使用&lt;a class="link" href="https://github.com/pantsel/konga" target="_blank" rel="noopener"&#10; &gt;Konga&lt;/a&gt;作为管理UI&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;POSTGRES_PASSWORD data docker-compose.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong ls data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postgresql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong cat POSTGRES_PASSWORD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kong&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong cat docker-compose.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &lt;span style="color:#e6db74"&gt;&amp;#39;3.7&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong_data: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong-net:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; external: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong-migrations:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_DOCKER_TAG&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong:latest&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; command: kong migrations bootstrap&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_DATABASE: postgres&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_DATABASE: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_DATABASE&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_HOST: db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_USER: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; secrets:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong-net&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deploy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart_policy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; condition: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong-migrations-up:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_DOCKER_TAG&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong:latest&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; command: kong migrations up &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; kong migrations finish&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_DATABASE: postgres&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_DATABASE: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_DATABASE&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_HOST: db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_USER: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; secrets:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong-net&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deploy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart_policy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; condition: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_DOCKER_TAG&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong:latest&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user: &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_ADMIN_ACCESS_LOG: /dev/stdout&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_ADMIN_ERROR_LOG: /dev/stderr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_ADMIN_LISTEN: &lt;span style="color:#e6db74"&gt;&amp;#39;0.0.0.0:8001&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_CASSANDRA_CONTACT_POINTS: db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_DATABASE: postgres&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_DATABASE: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_DATABASE&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_HOST: db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_USER: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PROXY_ACCESS_LOG: /dev/stdout&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PROXY_ERROR_LOG: /dev/stderr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; secrets:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong-net&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;8000:8000/tcp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1:8001:8001/tcp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;8443:8443/tcp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1:8444:8444/tcp&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; healthcheck:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; test: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;kong&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;health&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interval: 10s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout: 10s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; retries: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deploy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart_policy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; condition: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: postgres:9.5&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; POSTGRES_DB: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_DATABASE&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; POSTGRES_USER: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; secrets:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong_postgres_password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; healthcheck:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; test: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;pg_isready&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;-U&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interval: 30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout: 30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; retries: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deploy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart_policy:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; condition: on-failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stdin_open: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tty: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong-net&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - /Users/xxxx/docker/kong/data/postgresql:/var/lib/postgresql/data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; konga:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: pantsel/konga&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TOKEN_SECRET: channing.token&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DB_ADAPTER: postgres&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DB_HOST: db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DB_USER: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_USER&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DB_PASSWORD: kong&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DB_DATABASE: &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;KONG_PG_DATABASE&lt;span style="color:#66d9ef"&gt;:-&lt;/span&gt;kong&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 1337:1337&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - kong-net&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;secrets:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kong_postgres_password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; file: ./POSTGRES_PASSWORD&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行docker-composer up就可以看到&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;20ebe7885c0d kong:latest &lt;span style="color:#e6db74"&gt;&amp;#34;/docker-entrypoint.…&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; hours ago Up &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; seconds &lt;span style="color:#f92672"&gt;(&lt;/span&gt;healthy&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 0.0.0.0:8000-&amp;gt;8000/tcp, 127.0.0.1:8001-&amp;gt;8001/tcp, 0.0.0.0:8443-&amp;gt;8443/tcp, 127.0.0.1:8444-&amp;gt;8444/tcp kong_kong_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4a7a39c863ae pantsel/konga &lt;span style="color:#e6db74"&gt;&amp;#34;/app/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; hours ago Up &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; seconds 0.0.0.0:1337-&amp;gt;1337/tcp kong_konga_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aa732758fc51 postgres:9.5 &lt;span style="color:#e6db74"&gt;&amp;#34;docker-entrypoint.s…&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; hours ago Up &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; seconds &lt;span style="color:#f92672"&gt;(&lt;/span&gt;health: starting&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 5432/tcp kong_db_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;访问http://127.0.0.1:1337/即可以进入Konga 管理界面了。8000/8443端口是需要监听转发的端口，8001/8444则是Kong RESTFUl管理API的端口。这里也可以把8000/8443改为80/443，这样访问的时候就可以直接使用域名/localhost而不必加端口了。&lt;br&gt;&#10;注册登录进去后首先要添加Kong RESTFUl管理API的地址，这里使用的是docker环境，IP是动态分配的，所以使用链接名就可以了&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.20.50-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="562px" data-flex-grow="234" height="128" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.20.50-PM-300x128.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;连接上Kong API后可以看到dashboard列出了支持的插件&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-09-29-at-3.57.34-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="545px" data-flex-grow="227" height="132" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-09-29-at-3.57.34-PM-300x132.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;Kong里面的管理对象是service，路由转发/插件都是围绕service展开的，添加一个service&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.27.19-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="433px" data-flex-grow="180" height="166" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.27.19-PM-300x166.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.27.28-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="354px" data-flex-grow="147" height="203" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.27.28-PM-300x203.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;在它上面添加一个路由，这里我们在服务只监听以/api开头的url，并转发到后端服务器去&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.30.37-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.30.37-PM-300x167.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.30.48-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="260px" data-flex-grow="108" height="276" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.30.48-PM-300x276.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;注意这里在route里面的path里面也需要添加/api，否则转发的时候会出错（多拼api）。最简单就是service监听不指定path，在route里指定。一个service下面可以有多个转发路由，每个可以独立管理、设置超时等。&lt;br&gt;&#10;还可以为每个service绑定不同的插件进行处理，比如认证/安全/日志等等，这样就不用在不同的系统里面重复开发这些功能，使得各个团队更加专注也本业务开发&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.44.18-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="404px" data-flex-grow="168" height="178" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.44.18-PM-300x178.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.45.03-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="365px" data-flex-grow="152" height="197" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.45.03-PM-300x197.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.45.13-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="336px" data-flex-grow="140" height="214" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-4.45.13-PM-300x214.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;有效插件还可以进行流量限制、请求头/响应头修改等等。这些插件的功能需要基于consumer来开发管理，功能可以非常强大，详细可以参考&lt;a class="link" href="https://github.com/qianyugang/kong-docs-cn/blob/master/HUB/basic-auth.md" target="_blank" rel="noopener"&#10; &gt;文档&lt;/a&gt;。&lt;br&gt;&#10;Kong还有一项功能Upstream配置，与Nginx的&lt;a class="link" href="http://nginx.org/en/docs/http/ngx_http_upstream_module.html" target="_blank" rel="noopener"&#10; &gt;ngx_http_upstream_module&lt;/a&gt;差不多，可以作为负载均衡、流量分发控制使用。可以用命令行测试基于hostname的路由，&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ kong curl -i -X GET &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --url http://localhost:8000/ &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --header &lt;span style="color:#e6db74"&gt;&amp;#39;Host: dev1.example.com&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTP/1.1 &lt;span style="color:#ae81ff"&gt;404&lt;/span&gt; Not Found&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Date: Tue, &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;2020&lt;/span&gt; 08:41:58 GMT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Content-Type: application/json; charset&lt;span style="color:#f92672"&gt;=&lt;/span&gt;utf-8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection: keep-alive&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Content-Length: &lt;span style="color:#ae81ff"&gt;48&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;X-Kong-Response-Latency: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Server: kong/2.1.4&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;no Route matched with those values&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt; ➜ kong curl -i -X GET &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --url http://localhost:8000/ &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --header &lt;span style="color:#e6db74"&gt;&amp;#39;Host: dev.example.com&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTP/1.1 &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Content-Type: text/html; charset&lt;span style="color:#f92672"&gt;=&lt;/span&gt;UTF-8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Transfer-Encoding: chunked&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection: keep-alive&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Date: Tue, &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;2020&lt;/span&gt; 08:42:21 GMT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Server: Apache/2.2.15 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;CentOS&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;X-Powered-By: PHP/5.6.40&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Set-Cookie: PHPSESSID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0uc3aoc735j21sk3ni5s72vjc1; path&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Expires: Thu, &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; Nov &lt;span style="color:#ae81ff"&gt;1981&lt;/span&gt; 08:52:00 GMT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cache-Control: no-store, no-cache, must-revalidate, post-check&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0, pre-check&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pragma: no-cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Access-Control-Allow-Credentials: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Access-Control-Allow-Headers: X-CSRF-Token,Authorization,X-Accept-Charset,X-Accept,Content-Type&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;X-Kong-Upstream-Latency: &lt;span style="color:#ae81ff"&gt;8397&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;X-Kong-Proxy-Latency: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Via: kong/2.1.4&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;!DOCTYPE html PUBLIC &lt;span style="color:#e6db74"&gt;&amp;#34;-//W3C//DTD XHTML 1.0 Strict//EN&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作为一个API网关，Kong能做的很多。如果只是在本地简单的做反向代理，可以使用&lt;a class="link" href="https://github.com/jc21/nginx-proxy-manager" target="_blank" rel="noopener"&#10; &gt;nginx-proxy-manager&lt;/a&gt;，这也是一个基于Nginx开发的网关，根据WEB UI动态生成Nginx配置文件，然后执行/usr/sbin/nginx -s reload生效。有些参数不能通过UI配置（比如超时设置），可以直接写Nginx配置，upstream则支持直接转发tcp请求，支持websockets代理转发，甚至集成了&lt;a class="link" href="https://courages.us/lets-encrypt/" target="_blank" rel="noopener"&#10; &gt;Let’s encrypt&lt;/a&gt;自动申请SSL证书（需要验证域名）&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.03.05-PM.jpg" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="576px" data-flex-grow="240" height="125" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.03.05-PM-300x125.jpg" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.10.57-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="217px" data-flex-grow="90" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.10.57-PM-272x300.png" width="272"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.11.47-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="123px" data-flex-grow="51" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.11.47-PM-154x300.png" width="154"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.11.54-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="219px" data-flex-grow="91" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.11.54-PM-274x300.png" width="274"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.13.20-PM.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="666px" data-flex-grow="277" height="108" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/10/Screen-Shot-2020-10-27-at-5.13.20-PM-300x108.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;本地同样可以使用docker跑起来，默认监听80/443端口，81端口即管理界面&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager ls -lah&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; xxxx domain users 192B Sep &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 10:24 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; xxxx domain users 480B Sep &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 09:15 ..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r-- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; xxxx domain users 2.3K Sep &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 09:42 config.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; xxxx domain users 256B Sep &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 09:31 data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r-- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; xxxx domain users 740B Sep &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 10:24 docker-compose.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; xxxx domain users 96B Oct &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt; 16:38 letsencrypt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager cat docker-compose.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &lt;span style="color:#e6db74"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: &lt;span style="color:#e6db74"&gt;&amp;#39;jc21/nginx-proxy-manager:latest&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Public HTTP Port:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;80:80&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Public HTTPS Port:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;443:443&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Admin Web Port:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;81:81&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# TCP Forward Example:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;8022:8022&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Make sure this config.json file exists as per instructions above:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./config.json:/app/config/production.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./data:/data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./letsencrypt:/etc/letsencrypt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: jc21/mariadb-aria&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_ROOT_PASSWORD: &lt;span style="color:#e6db74"&gt;&amp;#39;npm&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_DATABASE: &lt;span style="color:#e6db74"&gt;&amp;#39;npm&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_USER: &lt;span style="color:#e6db74"&gt;&amp;#39;npm&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_PASSWORD: &lt;span style="color:#e6db74"&gt;&amp;#39;npm&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./data/mysql:/var/lib/mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3dd58e9cff1f jc21/nginx-proxy-manager:latest &lt;span style="color:#e6db74"&gt;&amp;#34;/init&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; weeks ago Up &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; days &lt;span style="color:#f92672"&gt;(&lt;/span&gt;healthy&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 0.0.0.0:80-81-&amp;gt;80-81/tcp, 0.0.0.0:443-&amp;gt;443/tcp, 0.0.0.0:8022-&amp;gt;8022/tcp nginx-proxy-manager_app_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;a033151b28ed jc21/mariadb-aria &lt;span style="color:#e6db74"&gt;&amp;#34;/scripts/run.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; weeks ago Up &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; days 3306/tcp nginx-proxy-manager_db_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;nginx-proxy-manager会将配置写在data目录下面，可以直接编辑这些文件，Nginx reload之后便会生效，可以看到这些文件，具体的加载规则参考&lt;a class="link" href="https://nginxproxymanager.com/advanced-config/#custom-nginx-configurations" target="_blank" rel="noopener"&#10; &gt;文档&lt;/a&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager ls data/nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dead_host default_host default_www dummycert.pem dummykey.pem proxy_host redirection_host stream temp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager cat data/nginx/proxy_host/1.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ------------------------------------------------------------&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# dev.example.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ------------------------------------------------------------&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; set $forward_scheme http;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; set $server &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.33.14&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; set $port 80;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 80;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listen &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:80;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name dev.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_log /data/logs/proxy_host-1.log proxy;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxy_connect_timeout 600;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxy_send_timeout 600;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxy_read_timeout 600;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;send_timeout 600;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /Login &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass https://login.example.com:443;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /api/v2 &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://192.168.33.14:9070;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /api/v3 &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass https://dev.ops.example.com:443;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /Chat &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass https://dev.ops.example.com:443;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /Catalog &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://192.168.33.1:3000;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /static &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://192.168.33.1:3000;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /css &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Scheme $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://192.168.33.1:3000;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Proxy!&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; include conf.d/include/proxy.conf;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Custom&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; include /data/nginx/custom/server_proxy&lt;span style="color:#f92672"&gt;[&lt;/span&gt;.&lt;span style="color:#f92672"&gt;]&lt;/span&gt;conf;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ nginx-proxy-manager cat data/nginx/stream/1.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ------------------------------------------------------------&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 8022 TCP: 1 UDP: 0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ------------------------------------------------------------&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 8022;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listen &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:8022;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass 192.168.33.14:22;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Custom&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; include /data/nginx/custom/server_stream&lt;span style="color:#f92672"&gt;[&lt;/span&gt;.&lt;span style="color:#f92672"&gt;]&lt;/span&gt;conf;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; include /data/nginx/custom/server_stream_tcp&lt;span style="color:#f92672"&gt;[&lt;/span&gt;.&lt;span style="color:#f92672"&gt;]&lt;/span&gt;conf;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在docker-compose.yml里面设置一下upstream监听转发的端口，就可以通过8022端口访问192.168.33.14的22端口了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  nginx-proxy-manager telnet 127.0.0.1 &lt;span style="color:#ae81ff"&gt;8022&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Trying 127.0.0.1...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connected to localhost.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Escape character is &lt;span style="color:#e6db74"&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SSH-2.0-OpenSSH_5.3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;^C^C^C^C^C^C^CConnection closed by foreign host.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不论是Kong还是nginx-proxy-manager均有提供API，极大的增强服务网关的可编程性，为动态上线/弹性扩展/自动化运维提供了便利。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://aws.amazon.com/cn/blogs/china/iaas-faas-serverless/" target="_blank" rel="noopener"&#10; &gt;从IaaS到FaaS—— Serverless架构的前世今生&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://developer.51cto.com/art/202004/615649.htm" target="_blank" rel="noopener"&#10; &gt;聊一聊微服务网关 Kong&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://cloud.tencent.com/developer/article/1435756" target="_blank" rel="noopener"&#10; &gt;KONG网关 — KongA管理UI使用&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://juejin.im/post/6844903924911063053" target="_blank" rel="noopener"&#10; &gt;云原生架构下的 API 网关实践： Kong （二）&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://xie.infoq.cn/article/ba0f7503c73b86126017c0d32" target="_blank" rel="noopener"&#10; &gt;微服务 API 网关 -Kong 详解&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://dev.to/bambattajb/creating-an-api-with-lua-using-openresty-42mc" target="_blank" rel="noopener"&#10; &gt;Creating a web API with Lua using Nginx OpenResty&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://cloud.tencent.com/developer/article/1027563" target="_blank" rel="noopener"&#10; &gt;Nginx基于TCP/UDP端口的四层负载均衡（stream模块）配置梳理&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.jianshu.com/p/45cb044ba99d" target="_blank" rel="noopener"&#10; &gt;Nginx支持TCP代理和负载均衡-stream模块&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.scienjus.com/api-gateway-and-netflix-zuul/" target="_blank" rel="noopener"&#10; &gt;聊聊 API Gateway 和 Netflix Zuul&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.servicemesher.com/envoy/intro/what_is_envoy.html" target="_blank" rel="noopener"&#10; &gt;Envoy 是什么？&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Nginx + Frp/Ngrok反向代理Webhook至本地</title><link>https://courages.us/nginx-frp-ngrok%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86webhook%E8%87%B3%E6%9C%AC%E5%9C%B0/</link><pubDate>Wed, 15 May 2019 20:21:20 +0800</pubDate><guid>https://courages.us/nginx-frp-ngrok%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86webhook%E8%87%B3%E6%9C%AC%E5%9C%B0/</guid><description>&lt;p&gt;跟第三方平台打交道，经常需要设置一个接受通知的Webhook，比如微信/Skype的回调。它们要求有一个可以在互联网上访问得了的入口，比如某个域名，如果是在本地开发的话，不好调试。通常使用花生壳来代理本地服务，但是花生壳有一些限制，比如端口。有些域名服务商，比如DNSPOD，Linode，提供相应的API，也可以自己搭建DDNS服务，但是也可能有端口访问限制。&lt;a class="link" href="https://github.com/fatedier/frp" target="_blank" rel="noopener"&#10; &gt;Frp&lt;/a&gt;/&lt;a class="link" href="https://ngrok.com/" target="_blank" rel="noopener"&#10; &gt;Ngrok&lt;/a&gt;都是Go语言开发的内网穿透工具，可以自己部署搭建。Frp是国人开发的一款反向代理软件，可以转发请求给位于NAT后面的机器，支持TCP，UDP，HTTP/HTTPS。Ngrok则是国外的一款内网穿透软件，也支持HTTP/HTTPS转发。这里使用Nginx作为反向代理服务器，接收互联网回调并转发给本地的Frp/Ngrok服务，由它们接收webhook请求并转发至本地开发环境。&lt;br&gt;&#10;前面&lt;a class="link" href="https://courages.us/centos-7%e4%b8%8a%e5%ae%89%e8%a3%85openvpn/" target="_blank" rel="noopener"&#10; &gt;使用OpenVpn搭建了私有网络&lt;/a&gt;，可以在Nginx里面配置转发给目标机器就可以了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vim /etc/nginx/conf.d/100-dev.example.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;内容如下&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 80;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name dev.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;301&lt;/span&gt; https://$host$request_uri;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 443;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name dev.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl on;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_session_cache builtin:1000 shared:SSL:10m;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_protocols TLSv1 TLSv1.1 TLSv1.2;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_prefer_server_ciphers on;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Real-IP $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://10.9.0.2/;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_redirect off;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里使用了&lt;a class="link" href="https://courages.us/lets-encrypt/" target="_blank" rel="noopener"&#10; &gt;let’s encryt&lt;/a&gt;的泛域名证书，官方并没有&lt;a class="link" href="https://certbot.eff.org/docs/using.html#dns-plugins" target="_blank" rel="noopener"&#10; &gt;对应的插件&lt;/a&gt;，但是DNSPOD有提供相应的API，第三方开发了一个插件自certbot-dns-dnspod，安装这个插件并且配置Dnspod的API Token：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ yum install certbot python2-certbot-nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ certbot --nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ pip install certbot-dns-dnspod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vim /etc/letsencrypt/dnspod.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;certbot_dns_dnspod:dns_dnspod_email &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;123@163.com&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;certbot_dns_dnspod:dns_dnspod_api_token &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;123,ca440********&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ chmod &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; /etc/letsencrypt/dnspod.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;手动请求证书&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ certbot certonly -a certbot-dns-dnspod:dns-dnspod --certbot-dns-dnspod:dns-dnspod-credentials /etc/letsencrypt/dnspod.conf --server https://acme-v02.api.letsencrypt.org/directory -d example.com -d &lt;span style="color:#e6db74"&gt;&amp;#34;*.example.com&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Saving debug log to /var/log/letsencrypt/letsencrypt.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Plugins selected: Authenticator certbot-dns-dnspod:dns-dnspod, Installer None&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting new HTTPS connection &lt;span style="color:#f92672"&gt;(&lt;/span&gt;1&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: acme-v02.api.letsencrypt.org&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Obtaining a new certificate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Performing the following challenges:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dns-01 challenge &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dns-01 challenge &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting new HTTPS connection &lt;span style="color:#f92672"&gt;(&lt;/span&gt;1&lt;span style="color:#f92672"&gt;)&lt;/span&gt;: dnsapi.cn&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Waiting &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; seconds &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS changes to propagate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; verification...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cleaning up challenges&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Resetting dropped connection: acme-v02.api.letsencrypt.org&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;IMPORTANT NOTES:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Congratulations! Your certificate and chain have been saved at:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /etc/letsencrypt/live/example.com/fullchain.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Your key file has been saved at:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /etc/letsencrypt/live/example.com/privkey.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Your cert will expire on 2019-08-04. To obtain a new or tweaked&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version of this certificate in the future, simply run certbot&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; again. To non-interactively renew *all* of your certificates, run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;certbot renew&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;*/1 * * * * /usr/local/qcloud/stargate/admin/start.sh &amp;gt; /dev/null 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &amp;amp;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - If you like Certbot, please consider supporting our work by:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Donating to ISRG / Let&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;s Encrypt: https://letsencrypt.org/donate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Donating to EFF: https://eff.org/donate-le&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls -la /etc/letsencrypt/live/example.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwx------ &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 ..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwxrwxrwx &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 cert.pem -&amp;gt; ../../archive/example.com/cert1.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwxrwxrwx &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 chain.pem -&amp;gt; ../../archive/example.com/chain1.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwxrwxrwx &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;39&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 fullchain.pem -&amp;gt; ../../archive/example.com/fullchain1.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lrwxrwxrwx &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 privkey.pem -&amp;gt; ../../archive/example.com/privkey1.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r-- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;692&lt;/span&gt; May &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 12:06 README&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;配置证书自动更新&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 0,12 * * * python -c &lt;span style="color:#e6db74"&gt;&amp;#39;import random; import time; time.sleep(random.random() * 3600)&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; certbot renew&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Frp的开发者已经提供了编译好的&lt;a class="link" href="https://github.com/fatedier/frp/releases" target="_blank" rel="noopener"&#10; &gt;frp服务端和客户端&lt;/a&gt;，下载即可使用。这里使用docker来运行Frp服务，使用这个&lt;a class="link" href="https://hub.docker.com/r/yangliu/frps/dockerfile" target="_blank" rel="noopener"&#10; &gt;Dockerfile&lt;/a&gt;，更改版本号为0.26.0，并编译&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker build . -t frps:0.26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;frps 0.26 8a87cb91d4de &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; hours ago 21.1MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;测试一下SSH代理服务，创建服务端配置文件&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p frp/conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vim frp/conf/frps.ini&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;frps.ini内容&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;common&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bind_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行一下frp服务端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#清除先前运行的容器&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker rm frp-server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker run --name frp-server -v /root/frp/conf:/conf -p 7000:7000 -p 6000:6000 frps:0.26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:17 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:136&lt;span style="color:#f92672"&gt;]&lt;/span&gt; frps tcp listen on 0.0.0.0:7000&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:17 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;root.go:204&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Start frps success&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:337&lt;span style="color:#f92672"&gt;]&lt;/span&gt; client login info: ip &lt;span style="color:#f92672"&gt;[&lt;/span&gt;110.87.98.82:61894&lt;span style="color:#f92672"&gt;]&lt;/span&gt; version &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0.26.0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; hostname &lt;span style="color:#f92672"&gt;[]&lt;/span&gt; os &lt;span style="color:#f92672"&gt;[&lt;/span&gt;linux&lt;span style="color:#f92672"&gt;]&lt;/span&gt; arch &lt;span style="color:#f92672"&gt;[&lt;/span&gt;386&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tcp.go:66&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;e8783ecea2085e15&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt; tcp proxy listen port &lt;span style="color:#f92672"&gt;[&lt;/span&gt;6000&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:398&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;e8783ecea2085e15&lt;span style="color:#f92672"&gt;]&lt;/span&gt; new proxy &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt; success&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:41 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy.go:82&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;e8783ecea2085e15&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt; get a new work connection: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;110.*.*.*:61894&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里映射了2个端口，端口7000是frp服务端监听的端口，以便客户端能够连接上；端口6000是需要服务端监听这个端口，以便提供反向代理服务，比如SSH。如果使用的是腾讯云，相应的端口需要在安全组放行。&lt;br&gt;&#10;客户端直接下对应的包，里面有配置试例。创建本地配置文件frpc.ini如下&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;common&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server_addr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 123.*.*.*&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type &lt;span style="color:#f92672"&gt;=&lt;/span&gt; tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;local_ip &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 127.0.0.1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;local_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;remote_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个配置即告诉服务端，将服务端的6000端口转发到本地的22端口。本地运行&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ./frpc -c ./frpc.ini.ssh &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:221&lt;span style="color:#f92672"&gt;]&lt;/span&gt; login to server success, get run id &lt;span style="color:#f92672"&gt;[&lt;/span&gt;e8783ecea2085e15&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, server udp port &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy_manager.go:137&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;e8783ecea2085e15&lt;span style="color:#f92672"&gt;]&lt;/span&gt; proxy added: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/04/22 06:41:27 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:144&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ssh&lt;span style="color:#f92672"&gt;]&lt;/span&gt; start proxy success&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后在服务端连接客户端。这里连接的是服务端的6000端口，会被转发给远程（局域网内）主机&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;rth@centos72&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ ssh -oPort&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6000&lt;/span&gt; vagrant@123.*.*.*&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The authenticity of host &lt;span style="color:#e6db74"&gt;&amp;#39;[123.*.*.*]:6000 ([123.*.*.*]:6000)&amp;#39;&lt;/span&gt; can&lt;span style="color:#e6db74"&gt;&amp;#39;t be established.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;RSA key fingerprint is SHA256:NhBO/PDL***********************.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;RSA key fingerprint is MD5:20:70:e2:*:*:*:*:*:*:*:*:*:*:*:*:*.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Are you sure you want to continue connecting (yes/no)? yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Warning: Permanently added &amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;123.*.*.*&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:6000&lt;span style="color:#e6db74"&gt;&amp;#39; (RSA) to the list of known hosts.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;vagrant@123.*.*.*&amp;#39;&lt;/span&gt;s password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Last login: Mon Apr &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; 06:39:07 &lt;span style="color:#ae81ff"&gt;2019&lt;/span&gt; from 10.0.2.2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;vagrant@centos64 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ exit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;logout&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection to 123.*.*.* closed.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Frp转发http服务很简单。在conf目录下创建配置frps.ini监听本机来自8080端口的HTTP请求&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;common&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bind_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vhost_http_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8080&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@VM_1_218_centos frp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# docker run --name frp-server -v /root/frp/conf:/conf -p 7000:7000 -p 8080:8080 frps:0.26&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:28 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:136&lt;span style="color:#f92672"&gt;]&lt;/span&gt; frps tcp listen on 0.0.0.0:7000&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:28 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:178&lt;span style="color:#f92672"&gt;]&lt;/span&gt; http service listen on 0.0.0.0:8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:28 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;root.go:204&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Start frps success&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:337&lt;span style="color:#f92672"&gt;]&lt;/span&gt; client login info: ip &lt;span style="color:#f92672"&gt;[&lt;/span&gt;123.*.*.*:56758&lt;span style="color:#f92672"&gt;]&lt;/span&gt; version &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0.26.0&lt;span style="color:#f92672"&gt;]&lt;/span&gt; hostname &lt;span style="color:#f92672"&gt;[]&lt;/span&gt; os &lt;span style="color:#f92672"&gt;[&lt;/span&gt;linux&lt;span style="color:#f92672"&gt;]&lt;/span&gt; arch &lt;span style="color:#f92672"&gt;[&lt;/span&gt;386&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;http.go:72&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; http proxy listen &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; host &lt;span style="color:#f92672"&gt;[&lt;/span&gt;test.example.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; location &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:398&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; new proxy &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; success&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:05 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy.go:82&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; get a new work connection: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;123.*.*.*:56758&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:05 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy.go:82&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; get a new work connection: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;123.*.*.*:56758&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:06 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy.go:82&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; get a new work connection: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;123.*.*.*:56758&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后配置Nginx转发请求&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vim /etc/nginx/conf.d/100-dev.example.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Real-IP $remote_addr;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Forwarded-Proto $scheme;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://127.0.0.1:8080/;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_redirect off;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;创建本地web传教客户端配置frpc.ini，将来自服务器dev.example.com:8080端口的HTTP请求转发至本地80端口&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;common&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server_addr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 123.*.*.*&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type &lt;span style="color:#f92672"&gt;=&lt;/span&gt; http&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;local_port &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;custom_domains &lt;span style="color:#f92672"&gt;=&lt;/span&gt; dev.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行本地客户端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 frp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ./frpc -c ./frpc.ini&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:221&lt;span style="color:#f92672"&gt;]&lt;/span&gt; login to server success, get run id &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt;, server udp port &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;proxy_manager.go:137&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;19f60a30aa924343&lt;span style="color:#f92672"&gt;]&lt;/span&gt; proxy added: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:26:51 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:144&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;web&lt;span style="color:#f92672"&gt;]&lt;/span&gt; start proxy success&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:37 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;E&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:127&lt;span style="color:#f92672"&gt;]&lt;/span&gt; work connection closed, EOF&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:37 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;control.go:228&lt;span style="color:#f92672"&gt;]&lt;/span&gt; control writer is closing&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2019/05/06 07:27:37 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;I&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;service.go:127&lt;span style="color:#f92672"&gt;]&lt;/span&gt; try to reconnect to server...&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;访问dev.example.com既可以看到本地web服务器页面。Frp还可以代理其他请求，也有在它基础上二次加工提供基于token认证的转发服务。&lt;br&gt;&#10;Ngrok 2.0以后不再开源，只能使用1.3版本的搭建。这里使用&lt;a class="link" href="https://github.com/hteen/docker-ngrok" target="_blank" rel="noopener"&#10; &gt;docker-ngrok&lt;/a&gt;来构建。Ngrok构建需要SSL证书，复制刚才生成的letsencypt证书并更改server.sh&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git clone https://github.com/hteen/docker-ngrok&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/fullchain.pem myfiles/base.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/fullchain.pem myfiles/fullchain.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/privkey.pem myfiles/privkey.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vim server.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set -e&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;DOMAIN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;**None**&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Please set DOMAIN&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exit &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; ! -f &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;MY_FILES&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/bin/ngrokd&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;ngrokd is not build,will be build it now...&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /bin/sh /build.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;MY_FILES&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/bin/ngrokd -tlsKey&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;MY_FILES&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/privkey.pem -tlsCrt&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;MY_FILES&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/fullchain.pem -domain&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;DOMAIN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -httpAddr&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;HTTP_ADDR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; -httpsAddr&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;HTTPS_ADDR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; -tunnelAddr&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;TUNNEL_ADDR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;构建Ngrok镜像&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@VM_1_218_centos docker-ngrok&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# docker build -t ngrok:1.3 .&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@VM_1_218_centos docker-ngrok&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# docker images&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ngrok 1.3 dc70190d6377 &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; seconds ago 260MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;frps 0.26 8a87cb91d4de &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; hours ago 21.1MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;alpine latest cdf98d1859c1 &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; days ago 5.53MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后交叉编译生成Linux/Mac/Windows平台的客户端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rm -rf assets/client/tls/ngrokroot.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/chain.pem assets/client/tls/ngrokroot.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rm -rf assets/server/tls/snakeoil.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/cert.pem assets/server/tls/snakeoil.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ rm -rf assets/server/tls/snakeoil.key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cp /etc/letsencrypt/live/example.com/privkey.pem assets/server/tls/snakeoil.key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ GOOS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;linux GOARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;amd64 make release-client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ GOOS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;windows GOARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;amd64 make release-client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ GOOS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;darwin GOARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;amd64 make release-client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在服务器上运行Ngrok服务，将8090端口请求转发给容器的80端口，并且映射容器的4443端口到服务器的7000端口，以便客户端连接&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@VM_1_218_centos docker-ngrok&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# docker run --name ngrok -e DOMAIN=&amp;#39;example.com&amp;#39; -p 8090:80 -p 8091:443 -p 7000:4443 -v /root/docker-ngrok/myfiles:/myfiles ngrok:1.3 /bin/sh /server.sh&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:21 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Info:83&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;registry&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tun&lt;span style="color:#f92672"&gt;]&lt;/span&gt; No affinity cache specified&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:21 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.Info:112&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Listening &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; public http connections on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:80&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:21 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.Info:112&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Listening &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; public https connections on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:443&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:21 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.Info:112&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Listening &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; control and proxy connections on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:4443&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:21 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Info:83&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Reporting every &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; seconds&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Info:83&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tun:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; New connection from 123.*.*.*:50529&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tun:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Waiting to read message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tun:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Reading message with length: &lt;span style="color:#ae81ff"&gt;125&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;tun:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Read message &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;Auth&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Payload&amp;#34;&lt;/span&gt;:&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;MmVersion&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;1.7&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;User&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Password&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;OS&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Arch&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;ClientId&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Info:83&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ctl:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Renamed connection tun:18e8cd42&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Info:83&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;registry&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ctl&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Registered control with id 1957f20b9b3ce3b76c7d8fc8b16276ed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ctl:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1957f20b9b3ce3b76c7d8fc8b16276ed&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Writing message: &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;AuthResp&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Payload&amp;#34;&lt;/span&gt;:&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;MmVersion&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;1.7&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;ClientId&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;1957f20b9b3ce3b76c7d8fc8b16276ed&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Error&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ctl:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1957f20b9b3ce3b76c7d8fc8b16276ed&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Writing message: &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;ReqProxy&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;Payload&amp;#34;&lt;/span&gt;:&lt;span style="color:#f92672"&gt;{}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;09:18:27 UTC 2019/05/07&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;DEBG&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ngrok/log.&lt;span style="color:#f92672"&gt;(&lt;/span&gt;*PrefixLogger&lt;span style="color:#f92672"&gt;)&lt;/span&gt;.Debug:79&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ctl:18e8cd42&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1957f20b9b3ce3b76c7d8fc8b16276ed&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Waiting to read message&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将刚才编译的客户端下载下来，创建grok.cfg，连接服务器的7000端口&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server_addr: &lt;span style="color:#e6db74"&gt;&amp;#34;example.com:7000&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;trust_host_root_certs: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;指定要监听的域名，及本地web端口&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./ngrok -config&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ngrok.cfg -subdomain&lt;span style="color:#f92672"&gt;=&lt;/span&gt;dev &lt;span style="color:#ae81ff"&gt;9010&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ngrok &lt;span style="color:#f92672"&gt;(&lt;/span&gt;Ctrl+C to quit&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tunnel Status online &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Version 1.7/1.7 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Forwarding http://dev.flexkit.cn -&amp;gt; 127.0.0.1:9010 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Forwarding https://dev.flexkit.cn -&amp;gt; 127.0.0.1:9010 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Web Interface 127.0.0.1:4040 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Conn 2 &lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Avg Conn Time 46.84ms &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTP Requests &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------- &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GET /teams &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; OK &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;请求dev.example.com即可以访问到本机9010端口的web服务。&lt;br&gt;&#10;附：&lt;a class="link" href="https://www.zerotier.com/" target="_blank" rel="noopener"&#10; &gt;ZeroTier&lt;/a&gt;是一个软件定义网络（SDN）软件，可以免费组建私有网络，当然也可以用来转发服务器请求至本地。&lt;/p&gt;&#10;&lt;p&gt;参考链接：：&lt;br&gt;&#10;&lt;a class="link" href="https://www.xncoding.com/2017/12/29/web/ngrok.html" target="_blank" rel="noopener"&#10; &gt;CentOS7搭建ngrok服务器&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/inconshreveable/ngrok" target="_blank" rel="noopener"&#10; &gt;inconshreveable/ngrok&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://hub.docker.com/r/hteen/ngrok/dockerfile" target="_blank" rel="noopener"&#10; &gt;hteen/ngrok&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://fengqi.me/unix/409.html" target="_blank" rel="noopener"&#10; &gt;搭建自己的 Ngrok 服务器, 并与 Nginx 并存&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.lylinux.net/article/2018/9/18/51.html" target="_blank" rel="noopener"&#10; &gt;使用Docker部署Ngrok实现内网穿透&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.v2ex.com/t/394739" target="_blank" rel="noopener"&#10; &gt;Laravel DDNS package，可代替花生壳之类的软件&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.jianshu.com/p/7294cf136b25" target="_blank" rel="noopener"&#10; &gt;通过DNSPod API实现动态域名解析&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://medium.com/@vista8/%E5%80%9F%E5%8A%A9dnspod-api%E5%AE%9A%E6%97%B6%E6%9B%B4%E6%96%B0%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90%E8%8E%B7%E5%8F%96%E6%A0%91%E8%8E%93%E6%B4%BE%E5%85%AC%E7%BD%91ip-1e460651596b" target="_blank" rel="noopener"&#10; &gt;借助dnspod-api定时更新域名解析获取树莓派公网ip&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://latlonworld.com/article/free-wildcard-ssl-with-lets-encrypt.html" target="_blank" rel="noopener"&#10; &gt;使用Let’s Encrypt生成通配符SSL证书&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://blog.sharpbai.com/2017/07/letsencrypt%E4%BD%BF%E7%94%A8dnspod%E9%AA%8C%E8%AF%81%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%E8%AF%81%E4%B9%A6/" target="_blank" rel="noopener"&#10; &gt;Letsencrypt使用DNSPOD验证自动更新证书&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://tommy.net.cn/2015/02/25/use-dnspod-as-ddns-on-openwrt/" target="_blank" rel="noopener"&#10; &gt;在 OpenWrt 环境下使用 DnsPod 来实现动态域名解析&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.cnblogs.com/kwongtai/p/6903420.html" target="_blank" rel="noopener"&#10; &gt;利用ssh反向代理以及autossh实现从外网连接内网服务器&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-with-ssl-as-a-reverse-proxy-for-jenkins" target="_blank" rel="noopener"&#10; &gt;How To Configure Nginx with SSL as a Reverse Proxy for Jenkins&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>在Raspberry Pi上面运行Docker</title><link>https://courages.us/%E5%9C%A8raspberry-pi%E4%B8%8A%E9%9D%A2%E8%BF%90%E8%A1%8Cdocker/</link><pubDate>Fri, 30 Sep 2016 23:36:00 +0800</pubDate><guid>https://courages.us/%E5%9C%A8raspberry-pi%E4%B8%8A%E9%9D%A2%E8%BF%90%E8%A1%8Cdocker/</guid><description>&lt;p&gt;公司有个项目是运行在Raspberry Pi上面，这个项目涉及到Perl，Python，Java Applet，并且未来Pi的数量可能达到上千个。最近碰到了一样的代码遵循一样的部署脚本，在不同的树莓派上运行竟然到不同的结果。于是也想将Docker应用到树莓派上面去，使用docker主要优点：&lt;br&gt;&#10;1 消除环境差异，程序运行所依赖的环境已经一起打包，随身携带了&lt;br&gt;&#10;2 简化配置，只有docker相关配置，不再需要每个语言单独配置&lt;br&gt;&#10;3 重复利用&lt;br&gt;&#10;4 方便升级，之前有差异时，是重写镜像。。&lt;br&gt;&#10;5 方便管理，可以使用docker已有的工具来管理&lt;br&gt;&#10;6 性能接近原生应用&lt;/p&gt;&#10;&lt;p&gt;Raspberry Pi在jessie这个版本就已经支持了docker，检查版本：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ lsb_release -da&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;No LSB modules are available.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Distributor ID: Raspbian&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description: Raspbian GNU/Linux 8.0 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;jessie&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Release: 8.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Codename: jessie&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你的版本已经支持，直接执行以下命令就可以了：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -sSL https://get.docker.com | sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你的版本不支持，你需要升级系统或重新刷镜像，可以采用hypriot&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#下载&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wget https://downloads.hypriot.com/hypriotos-rpi-v1.0.0.img.zip&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#解压&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unzip hypriotos-rpi-v1.0.0.img.zip&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#查找 SD card ID&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lsblk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#查找类似/dev/mmcblk0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#弹出SD卡&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;umount /run/media/mac/8734-1E4C&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#将镜像写入 SD card&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo dd &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hypriotos-rpi-v1.0.0.img of&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/dev/mmcblk0 bs&lt;span style="color:#f92672"&gt;=&lt;/span&gt;1m&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后启动，默认的用户名/密码是pirate/hypriot。&lt;br&gt;&#10;当然也可以采用Debian或者是&lt;a class="link" href="https://wiki.alpinelinux.org/wiki/Raspberry_Pi" target="_blank" rel="noopener"&#10; &gt;Alpine Linux&lt;/a&gt;来&lt;a class="link" href="https://wiki.alpinelinux.org/wiki/Docker" target="_blank" rel="noopener"&#10; &gt;定制&lt;/a&gt;（Raspberry Pi仅支持 arm版本的系统，并且只能在arm平台上构建，或者&lt;a class="link" href="https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/" target="_blank" rel="noopener"&#10; &gt;这个&lt;/a&gt;）。&lt;br&gt;&#10;运行测试一下:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -d -p 80:80 hypriot/rpi-busybox-httpd&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;访问以下树莓派的IP，就会看到一个非常神器的网页，而这个容器仅仅几M。在&lt;a class="link" href="https://hub.docker.com/u/hypriot/" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;可以看到基于hypriot的好几个镜像，也可以搜索其他的raspberry pi镜像。&lt;br&gt;&#10;现在我们使用hypriot/rpi-python来构建一个使用Python Selenium测试带有Java Applet的网页：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -idt -P --name web hypriot/rpi-python&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker attach web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;进入到容器里面，执行以下命令：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装openjdk&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install openjdk-7-jdk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装Firefox&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install iceweasel&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装Java Applet插件&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install icedtea-7-plugin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装虚拟桌面&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install xvfb&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装Python包管理工具&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install python-pip&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装selenium&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo pip install selenium&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#安装Python虚拟桌面库&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo pip install pyvirtualdisplay&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;创建测试test.py：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium &lt;span style="color:#f92672"&gt;import&lt;/span&gt; webdriver&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium.webdriver.common.keys &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Keys&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; time&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; pyvirtualdisplay &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Display&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium.webdriver.common.desired_capabilities &lt;span style="color:#f92672"&gt;import&lt;/span&gt; DesiredCapabilities&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium.webdriver.firefox.firefox_binary &lt;span style="color:#f92672"&gt;import&lt;/span&gt; FirefoxBinary&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Display(visible&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, size&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;800&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display&lt;span style="color:#f92672"&gt;.&lt;/span&gt;start()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;caps &lt;span style="color:#f92672"&gt;=&lt;/span&gt; DesiredCapabilities&lt;span style="color:#f92672"&gt;.&lt;/span&gt;FIREFOX&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;caps[&lt;span style="color:#e6db74"&gt;&amp;#34;marionette&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#caps[&amp;#34;binary&amp;#34;] = &amp;#34;/usr/bin/firefox&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;firefox_binary &lt;span style="color:#f92672"&gt;=&lt;/span&gt; FirefoxBinary(&lt;span style="color:#e6db74"&gt;&amp;#34;/usr/bin/firefox&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; webdriver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;FirefoxProfile()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_preference(&lt;span style="color:#e6db74"&gt;&amp;#34;security.enable_java&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_preference(&lt;span style="color:#e6db74"&gt;&amp;#34;plugin.state.java&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver &lt;span style="color:#f92672"&gt;=&lt;/span&gt; webdriver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Firefox(firefox_profile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;fp,firefox_binary&lt;span style="color:#f92672"&gt;=&lt;/span&gt;firefox_binary)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;maximize_window()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;http://businessconnect.telus.com/bandwidth/en_us/index.html?voip=on&amp;amp;voiplines=1&amp;amp;testlength=15&amp;amp;codec=g711&amp;amp;_=1470641590&amp;amp;startTest=on&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sleep(&lt;span style="color:#ae81ff"&gt;120&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mos &lt;span style="color:#f92672"&gt;=&lt;/span&gt; driver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_element_by_class_name(&lt;span style="color:#e6db74"&gt;&amp;#34;sectiontitle18&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;find_element_by_tag_name(&lt;span style="color:#e6db74"&gt;&amp;#34;span&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_attribute(&lt;span style="color:#e6db74"&gt;&amp;#34;innerHTML&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print mos&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;close()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display&lt;span style="color:#f92672"&gt;.&lt;/span&gt;stop()&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行测试用例：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python test.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果仅仅是这样子，是行不通的，Java Applet的安全询问弹窗超出了浏览器范围是点击不到的，需要更为强大的组件来做，比如。&lt;br&gt;&#10;这里采用取巧的方法，首先把pyvirtualdisplay相关代码注释掉，在界面上观察具体的执行效果，并点击安全询问，运行通过。然后取消注释，再次运行，就可以了。最后将运行通过的配置文件/root/.icedtea目录拷贝出来，放到其他的树莓派里面就可以了。&lt;br&gt;&#10;如果碰到报错”selenium.common.exceptions.WebDriverException: Can’t load the profile”，通常是说Firefox或selenium版本太低，如果检查都不是，需要修改WebDriver的超时时间&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nano /usr/local/lib/python2.7/dist-packages/selenium/webdriver/firefox/webdriver.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;timeout从30秒改为120秒：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WebDriver&lt;/span&gt;(RemoteWebDriver):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# There is no native event support on Mac&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NATIVE_EVENTS_ALLOWED &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sys&lt;span style="color:#f92672"&gt;.&lt;/span&gt;platform &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;darwin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self, firefox_profile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;, firefox_binary&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;, timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;120&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;修改为容器后，提交变更：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@black-pearl:/home/pirate# docker ps -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;04762770df2d hypriot/rpi-python &lt;span style="color:#e6db74"&gt;&amp;#34;bash&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; days ago Up &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; days web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@black-pearl:/home/pirate# docker commit 04762770df2d hypriot/rpi-python&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@black-pearl:/home/pirate# docker rm web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行新镜像&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#docker run -idt -P --name web hypriot/rpi-python&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#映射程序目录和配置文件进去&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -idt -P --name web -v /home/pi:/home/pi -v /home/pi/.icedtea:/root/.icedtea hypriot/rpi-python&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;程序正常运行后，可以将这个镜像打包：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker save -o hypriot.tar hypriot/rpi-python:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;分发给其他树莓派运行：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker load --input hypriot.tar&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -idt -P --name web -v /home/pi:/home/pi -v /home/pi/.icedtea:/root/.icedtea hypriot/rpi-python&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样子便可以利用docker工具来管理这个应用程序，比起原本复杂的环境配置要简单很多。&lt;/p&gt;&#10;&lt;p&gt;在查找Pi可用镜像的时候，顺便发现了一个IOT（internet of things）管理平台：&lt;a class="link" href="https://resin.io/" target="_blank" rel="noopener"&#10; &gt;resin&lt;/a&gt;。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/docker/docker/pull/24815" target="_blank" rel="noopener"&#10; &gt;add support to install Docker on raspbian/jessie&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://blog.hypriot.com/getting-started-with-docker-on-your-arm-device/" target="_blank" rel="noopener"&#10; &gt;Getting started with Docker on your Raspberry Pi&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://blog.hypriot.com/getting-started-with-docker-and-linux-on-the-raspberry-pi/" target="_blank" rel="noopener"&#10; &gt;How to get Docker running on your Raspberry Pi using Linux&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.raspberrypi.org/forums/viewtopic.php?f=63&amp;amp;t=129320" target="_blank" rel="noopener"&#10; &gt;Getting selenium python to work on Raspberry Pi Model B&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>使用Docker Compose管理Docker容器</title><link>https://courages.us/%E4%BD%BF%E7%94%A8docker-compose%E7%AE%A1%E7%90%86docker%E5%AE%B9%E5%99%A8/</link><pubDate>Fri, 30 Sep 2016 00:10:36 +0800</pubDate><guid>https://courages.us/%E4%BD%BF%E7%94%A8docker-compose%E7%AE%A1%E7%90%86docker%E5%AE%B9%E5%99%A8/</guid><description>&lt;p&gt;&lt;a class="link" href="https://courages.us/%e6%9e%84%e5%bb%ba%e5%9f%ba%e4%ba%8edocker%e7%9a%84nginx-php-fpm-phalcon%e9%95%9c%e5%83%8f/" target="_blank" rel="noopener"&#10; &gt;上一篇&lt;/a&gt;创建了一个PHP的运行环境，现在需要一个MySQL服务，直接运行：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name rocket-mysql -v /home/rocketfish/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;root -d mysql:5.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;就自动下载并得到一个mysql版本为5.7的服务镜像。&lt;br&gt;&#10;这时候，要运行一个Web服务我们需要运行两次的docker run才可以，如果还有更多的Web容器或其他的服务容器呢？&lt;br&gt;&#10;Docker官方提倡一个容器仅提供一个服务，多个服务/容器可以使用docker-compose来管理。&lt;br&gt;&#10;docker-compose本身是一个Python写的工具，可以直接通过pip安装：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# sudo pip install --upgrade pip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你本地并没有Python环境，也可以采用docker-compose的docker镜像来运行：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# curl -L https://github.com/docker/compose/releases/download/1.8.0/run.sh &amp;gt; /usr/local/bin/docker-compose&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose --version&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#开始下载镜像，建议用第一种&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查看帮助&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker-compose -h&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Define and run multi-container applications with Docker.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Usage:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker-compose &lt;span style="color:#f92672"&gt;[&lt;/span&gt;-f &amp;lt;arg&amp;gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;options&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;COMMAND&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;ARGS...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker-compose -h|--help&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Options:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -f, --file FILE Specify an alternate compose file &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default: docker-compose.yml&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p, --project-name NAME Specify an alternate project name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;default: directory name&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --verbose Show more output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v, --version Print version and exit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H, --host HOST Daemon socket to connect to&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tls Use TLS; implied by --tlsverify&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tlscacert CA_PATH Trust certs signed only by this CA&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tlscert CLIENT_CERT_PATH Path to TLS certificate file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tlskey TLS_KEY_PATH Path to TLS key file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tlsverify Use TLS and verify the remote&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --skip-hostname-check Don&lt;span style="color:#e6db74"&gt;&amp;#39;t check the daemon&amp;#39;&lt;/span&gt;s hostname against the name specified&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in the client certificate &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; example &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; your docker host&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; is an IP address&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Commands:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; build Build or rebuild services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bundle Generate a Docker bundle from the Compose file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config Validate and view the compose file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; create Create services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; down Stop and remove containers, networks, images, and volumes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; events Receive real time events from containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exec Execute a command in a running container&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; help Get help on a command&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kill Kill containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; logs View output from containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pause Pause services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port Print the public port &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; a port binding&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps List containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pull Pulls service images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; push Push service images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart Restart services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rm Remove stopped containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; run Run a one-off command&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scale Set number of containers &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; a service&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start Start services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop Stop services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; unpause Unpause services&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; up Create and start containers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version Show the Docker-Compose version information&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些命令包括了创建/启动/停止/暂停/继续运行容器。&lt;br&gt;&#10;首先要创建docker-compose.yml，这是一个&lt;a class="link" href="http://yaml.org/" target="_blank" rel="noopener"&#10; &gt;YAML&lt;/a&gt;格式的文档&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vim docker-compose.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;内容如下：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &amp;#39;2&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: mysql:5.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &amp;#34;3306:3306&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_ROOT_PASSWORD: root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_DATABASE: web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_USER: root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MYSQL_PASSWORD: rootweb&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./db/data:/var/lib/mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; web:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &amp;#34;80:80&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WEB_DB_HOST: db:3306&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WEB_DB_PASSWORD: root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./web/html:/var/www/html/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; links:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里的environment定义了环境变量，比如host的MAC，就可以在docker容器的系统变量里面得到，各个编程语言都有获取系统环境变量的方法。这些变量也可以组织起来放在文件里面加载进去，参考&lt;a class="link" href="https://docs.docker.com/compose/environment-variables/" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。&lt;br&gt;&#10;这里的volumes定义了要映射进容器的文件或文件夹或者数据容器，可以参考&lt;a class="link" href="https://docs.docker.com/engine/tutorials/dockervolumes/" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。注意，多个容器共享同一个目录，会出现写冲突，比如MySQL，多个实例，数据目录需要分开。所以设计好你的程序，哪一部分是需要只读的（可以共享)，哪一部分是需要写的；写的部分是否可以放到各自临时目录，或者其他公共服务里面。&lt;br&gt;&#10;运行并查看&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose up -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Creating network &lt;span style="color:#e6db74"&gt;&amp;#34;composeweb_default&amp;#34;&lt;/span&gt; with the default driver&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Creating composeweb_db_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Creating composeweb_web_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Name Command State Ports &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;------------------------------------------------------------------------------------&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;composeweb_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306-&amp;gt;3306/tcp &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;composeweb_web_1 /start.sh Up 443/tcp, 0.0.0.0:80-&amp;gt;80/tcp &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#也可以使用原来的命令&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;efbdaf257748 nginx-php-fpm:phalcon &lt;span style="color:#e6db74"&gt;&amp;#34;/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; seconds 0.0.0.0:80-&amp;gt;80/tcp, 443/tcp composeweb_web_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;a6935d20911e mysql:5.7 &lt;span style="color:#e6db74"&gt;&amp;#34;docker-entrypoint.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; seconds 0.0.0.0:3306-&amp;gt;3306/tcp composeweb_db_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker-compose up -d ，将会在后台启动并运行所有的容器。&lt;br&gt;&#10;docker-compose仅仅提供了对多个docker服务的管理，仍然可以在这些容器上运行原来的docker命令。检查下web容器的IP：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker inspect composeweb_web_1 | grep IPAddress&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;SecondaryIPAddresses&amp;#34;&lt;/span&gt;: null,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;IPAddress&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;IPAddress&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;172.18.0.3&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后访问：http://172.18.0.3/ 就可以看到web页面了。&lt;br&gt;&#10;如果想要停止服务，可以用docker-compose stop：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose stop db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Stopping composeweb_db_1 ... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose stop web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Stopping composeweb_web_1 ... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再次启动，得到相同名称的服务:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:/home/compose-web# docker-compose up -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting composeweb_db_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting composeweb_web_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各个容器的名称也可以在配置文件里面通过参数container_name来指定。&lt;br&gt;&#10;docker-compose的配置还有很多其他的&lt;a class="link" href="https://docs.docker.com/compose/compose-file/" target="_blank" rel="noopener"&#10; &gt;参数&lt;/a&gt;，可以参考&lt;a class="link" href="https://docs.docker.com/compose/compose-file/#ipv4-address-ipv6-address" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。比如刚才我们通过docker inspect来查找容器IP，也可以配置成静态IP：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &amp;#39;2&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app_net:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ipv4_address: 172.18.0.10&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ipv6_address: 2001:3984:3989::10&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;networks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app_net:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver: bridge&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver_opts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; com.docker.network.enable_ipv6: &amp;#34;true&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ipam:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver: default&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - subnet: 172.18.0.0/24&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gateway: 172.18.0.1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - subnet: 2001:3984:3989::/64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gateway: 2001:3984:3989::1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;也可以&lt;a class="link" href="https://docs.docker.com/compose/networking/" target="_blank" rel="noopener"&#10; &gt;自定义网络&lt;/a&gt;。&lt;br&gt;&#10;刚才我们的配置文件里面直接指定了镜像，也可以指定Dockerfile镜像构建，假如Dockerfile在web目录下面:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;build:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context: ./web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;或者直接指明Dockerfile：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;build:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context: .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dockerfile: Dockerfile-alternate&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实际上，docker-compose的配置已经覆盖了&lt;a class="link" href="https://docs.docker.com/engine/reference/builder/" target="_blank" rel="noopener"&#10; &gt;Dockerfile&lt;/a&gt;的配置项，也可以直接用于构建多个docker服务，比如指定运行的命令&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;command: [/bin/bash]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里的入口程序，如果不能持续运行的话，运行完成后，docker就会退出。所以如果你需要可以后台运行的docker容器，那么入口程序，就必须保持一个程序在前台运行，不退出，比如运行crontab的镜像，入口程序可以是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cron &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;cron这个程序是在后台运行的，如果不配合前台程序bash，容器执行玩cron就会退出了。其他运行crontab的容器，大都是强制一个程序在前台不退出，比如&lt;a class="link" href="https://www.ekito.fr/people/run-a-cron-job-with-docker/" target="_blank" rel="noopener"&#10; &gt;这个&lt;/a&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cron &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; tail -f /var/log/cron.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里需要注意一下，通过docker设置的environment values在容器内的cli下面执行时取不到的，比如printenv，使用cron后台运行时取不到外部设置的变量，但是手动执行时又可以。这些外部环境变量只能在ENTRYPOINT或者CMD所执行的shell里面去设置，比如在CMD执行start.sh:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;printenv | grep -E &lt;span style="color:#e6db74"&gt;&amp;#34;^HOST&amp;#34;&lt;/span&gt; &amp;gt; /root/env.conf &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cron &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker compose还可以跟&lt;a class="link" href="https://docs.docker.com/compose/swarm/" target="_blank" rel="noopener"&#10; &gt;Docker Swarm&lt;/a&gt;结合。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://docs.docker.com/compose/install/" target="_blank" rel="noopener"&#10; &gt;Install Docker Compose&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://docs.docker.com/compose/wordpress/" target="_blank" rel="noopener"&#10; &gt;Quickstart: Docker Compose and WordPress&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/yeasy/docker_practice/blob/master/compose/yaml_file.md" target="_blank" rel="noopener"&#10; &gt;YAML 模板文件&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.linux.com/learn/introduction-docker-compose-tool-multi-container-applications" target="_blank" rel="noopener"&#10; &gt;Introduction to Docker Compose Tool for Multi-Container Applications&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/yeasy/docker_practice/blob/master/dockerfile/basic_structure.md" target="_blank" rel="noopener"&#10; &gt;Dockerfile基本结构&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/" target="_blank" rel="noopener"&#10; &gt;How to Get Environment Variables Passed Through docker-compose to the Containers&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://ypereirareis.github.io/blog/2016/02/29/docker-crontab-environment-variables/" target="_blank" rel="noopener"&#10; &gt;Access environment variables from crontab into a docker container&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://stackoverflow.com/questions/27771781/how-can-i-access-docker-set-environment-variables-from-a-cron-job" target="_blank" rel="noopener"&#10; &gt;How can I access Docker set Environment Variables From a Cron Job&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://segmentfault.com/q/1010000000417103" target="_blank" rel="noopener"&#10; &gt;Dockerfile里指定执行命令用ENTRYPOING和用CMD有何不同？&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://stackoverflow.com/questions/21553353/what-is-the-difference-between-cmd-and-entrypoint-in-a-dockerfile" target="_blank" rel="noopener"&#10; &gt;What is the difference between CMD and ENTRYPOINT in a Dockerfile?&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://til.codes/docker-run-vs-cmd-vs-entrypoint/" target="_blank" rel="noopener"&#10; &gt;Docker difference between run, cmd, entrypoint commands&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>基于Docker的Nginx + PHP-FPM + Phalcon镜像</title><link>https://courages.us/%E6%9E%84%E5%BB%BA%E5%9F%BA%E4%BA%8Edocker%E7%9A%84nginx-php-fpm-phalcon%E9%95%9C%E5%83%8F/</link><pubDate>Wed, 28 Sep 2016 23:34:40 +0800</pubDate><guid>https://courages.us/%E6%9E%84%E5%BB%BA%E5%9F%BA%E4%BA%8Edocker%E7%9A%84nginx-php-fpm-phalcon%E9%95%9C%E5%83%8F/</guid><description>&lt;p&gt;&lt;a class="link" href="https://courages.us/ubuntu-16-04-%e4%b8%8a%e5%ae%89%e8%a3%85docker/" target="_blank" rel="noopener"&#10; &gt;上一篇&lt;/a&gt;简单介绍了Docker的安装，运行，这一篇来构建一个基于Nginx和PHP-FPM的Phalcon镜像。在官方找了以下，单独的Nginx和PHP镜像更加流行，混合的反倒不是很受欢迎。其实官方并不提倡在一个容器里面运行多个服务，最好是一个容器只对外提供一个服务：一个容器启动时仅仅运行一个命令（其实里面可以包含多个），也方便部署扩展升级。多个服务之间可以使用&lt;a class="link" href="https://github.com/yeasy/docker_practice/blob/master/compose/yaml_file.md" target="_blank" rel="noopener"&#10; &gt;Docker Compose&lt;/a&gt;来管理。但是Docker并不阻止创建包含多个服务器的镜像，为了方便，所以我们仍然可以自己构建。&lt;br&gt;&#10;构建镜像可以有好几种方式，比如基于&lt;a class="link" href="https://hub.docker.com/_/alpine/" target="_blank" rel="noopener"&#10; &gt;Alpine Linux&lt;/a&gt;或&lt;a class="link" href="https://github.com/phusion/baseimage-docker" target="_blank" rel="noopener"&#10; &gt;phusion/baseimage-docker&lt;/a&gt;构建，或者基于Ubuntu，CentOS等构建，又或者在PHP，Nginx的基础镜像上构建。注意：如果要采用Ubuntu或者CentOS构建，可能需要一些额外的&lt;a class="link" href="http://phusion.github.io/baseimage-docker/" target="_blank" rel="noopener"&#10; &gt;工作&lt;/a&gt;，以便保持镜像轻量稳定运行。&lt;br&gt;&#10;这里采用已有的&lt;a class="link" href="https://hub.docker.com/r/richarvey/nginx-php-fpm/" target="_blank" rel="noopener"&#10; &gt;richarvey/nginx-php-fpm&lt;/a&gt;来构建，它是一个基于&lt;a class="link" href="https://hub.docker.com/_/nginx/" target="_blank" rel="noopener"&#10; &gt;Nginx官方镜像&lt;/a&gt;来构建的。&lt;br&gt;&#10;从&lt;a class="link" href="https://github.com/ngineered/nginx-php-fpm" target="_blank" rel="noopener"&#10; &gt;Github&lt;/a&gt;上拉取相关文件从Dockerfile构建：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo git clone https://github.com/ngineered/nginx-php-fpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo docker build -t nginx-php-fpm:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关于Dockerfile的相关解释，可以参考&lt;a class="link" href="https://github.com/yeasy/docker_practice/blob/master/dockerfile/basic_structure.md" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。当然也可以直接拉取镜像使用&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo docker pull richarvey/nginx-php-fpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 也可以直接运行，会自动拉取&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#$ sudo docker run -d richarvey/nginx-php-fpm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查看本地的镜像，连单独的nginx也来了：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx-php-fpm latest 4fc9ac9f2945 &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; hours ago 228.5 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx mainline-alpine 00bc1e841a8f &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; days ago 54.21 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里的mainline-alpine是指基于&lt;a class="link" href="https://alpinelinux.org/" target="_blank" rel="noopener"&#10; &gt;Alpine Linux&lt;/a&gt;构建的。Alpine Linux是一个仅有5M大小的linux系统，采用apk add/search来安装/查找相应软件，有许多镜像都是基于它构建的，官方PHP镜像也有基于它构建的Docker镜像。&lt;br&gt;&#10;然后运行nginx-php-fpm：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name web -d richarvey/nginx-php-fpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker inspect命令用来查看容器的相关信息，查看下分配的IP：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker inspect web | grep IPAddress&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;SecondaryIPAddresses&amp;#34;&lt;/span&gt;: null,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;IPAddress&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;172.17.0.2&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;IPAddress&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;172.17.0.2&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后在浏览器里面访问：http://172.17.0.2/就可以看到phpinfo的页面。到这里，Nginx + PHP的web容器就已经运行起来了，对应的Nginx和PHP进程可以在宿主机器上直接查看：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# ps aux | grep nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root &lt;span style="color:#ae81ff"&gt;18167&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;13696&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4300&lt;/span&gt; pts/6 S 01:47 0:00 nginx: master process /usr/sbin/nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18168&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;14144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1868&lt;/span&gt; pts/6 S 01:47 0:00 nginx: worker process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18169&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;14144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1868&lt;/span&gt; pts/6 S 01:47 0:00 nginx: worker process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18170&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;14144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1868&lt;/span&gt; pts/6 S 01:47 0:00 nginx: worker process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18171&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;14144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1868&lt;/span&gt; pts/6 S 01:47 0:00 nginx: worker process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18172&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;14144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1868&lt;/span&gt; pts/6 S 01:47 0:00 nginx: worker process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root &lt;span style="color:#ae81ff"&gt;18190&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;21292&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1012&lt;/span&gt; pts/18 S+ 01:47 0:00 grep --color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;auto nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# ps aux | grep php-fpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root &lt;span style="color:#ae81ff"&gt;18166&lt;/span&gt; 0.0 0.2 &lt;span style="color:#ae81ff"&gt;167880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;23364&lt;/span&gt; pts/6 S 01:47 0:00 php-fpm: master process &lt;span style="color:#f92672"&gt;(&lt;/span&gt;/etc/php5/php-fpm.conf&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18173&lt;/span&gt; 0.0 0.1 &lt;span style="color:#ae81ff"&gt;167880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8620&lt;/span&gt; pts/6 S 01:47 0:00 php-fpm: pool www&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18174&lt;/span&gt; 0.0 0.1 &lt;span style="color:#ae81ff"&gt;167880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8620&lt;/span&gt; pts/6 S 01:47 0:00 php-fpm: pool www&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemd+ &lt;span style="color:#ae81ff"&gt;18175&lt;/span&gt; 0.0 0.1 &lt;span style="color:#ae81ff"&gt;167880&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8620&lt;/span&gt; pts/6 S 01:47 0:00 php-fpm: pool www&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root &lt;span style="color:#ae81ff"&gt;18192&lt;/span&gt; 0.0 0.0 &lt;span style="color:#ae81ff"&gt;21292&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1032&lt;/span&gt; pts/18 S+ 01:47 0:00 grep --color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;auto php-fpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接下来要为这个容器添加Phalcon扩展。首先要进入容器里面，使用docker attach命令进入：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker attach web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;结果在这里等了半天进不去。。。。查看下当前镜像入口程序：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;94176348a939 nginx-php-fpm &lt;span style="color:#e6db74"&gt;&amp;#34;/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; seconds 80/tcp, 443/tcp web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个容器启动的时候运行的是start.sh这个脚本，这个脚本运行了&lt;a class="link" href="http://supervisord.org/" target="_blank" rel="noopener"&#10; &gt;Supervisor&lt;/a&gt;工具。于是重新启动容器，运行/bin/bash&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#终止容器运行&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker stop web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#删除容器&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker rm web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#重新运行&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name web -d -t -i nginx-php-fpm /bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ea21e10df702644a83ed75930b30c7764a786c4feabdf17cd868f86640137c47&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ea21e10df702 nginx-php-fpm &lt;span style="color:#e6db74"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; seconds 80/tcp, 443/tcp web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker attach web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#进来了&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bin etc lib media proc run srv sys usr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dev home linuxrc mnt root sbin start.sh tmp var&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;就可以进去了。&lt;br&gt;&#10;先安装编译相关工具包：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# apk --no-cache add php5-dev&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# apk --no-cache add gcc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# apk --no-cache add make&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# apk --no-cache add autoconf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# apk --no-cache add libc-dev&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;1/2&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Installing musl-dev &lt;span style="color:#f92672"&gt;(&lt;/span&gt;1.1.14-r12&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;2/2&lt;span style="color:#f92672"&gt;)&lt;/span&gt; Installing libc-dev &lt;span style="color:#f92672"&gt;(&lt;/span&gt;0.7-r0&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OK: &lt;span style="color:#ae81ff"&gt;334&lt;/span&gt; MiB in &lt;span style="color:#ae81ff"&gt;106&lt;/span&gt; packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编译安装Phalcon：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# cd /home&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# git clone --depth&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; git://github.com/phalcon/cphalcon.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# cd cphalcon/build&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# ./install&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# ls -la /usr/lib/php5/modules/ | grep phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rwxr-xr-x &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;5045264&lt;/span&gt; Sep &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; 17:34 phalcon.so&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;更改PHP扩展的配置：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# cd /etc/php5/conf.d/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# vi phalcon.ini&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#添加以下内容&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#extension=phalcon.so&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#检查扩展是否加载成功&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# php -i | grep phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/etc/php5/conf.d/phalcon.ini,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; enabled&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.db.escape_identifiers &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.db.force_casting &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.cast_on_hydrate &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.column_renaming &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.enable_implicit_joins &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.enable_literals &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.events &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.exception_on_failed_save &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.ignore_unknown_columns &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.late_state_binding &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; Off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.not_null_validations &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon.orm.virtual_foreign_keys &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; On&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OLDPWD &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; /home/cphalcon/build&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;_SERVER&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;OLDPWD&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; /home/cphalcon/build&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;_ENV&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;OLDPWD&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; /home/cphalcon/build&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;加载成功了，需要保持本次镜像变更。首先退出容器：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# cd /home&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#删除各种不必要的东西，比如gcc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# rm -rf cphalcon/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bash-4.3# exit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exit&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后查看版本并提交变更：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ea21e10df702 nginx-php-fpm &lt;span style="color:#e6db74"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; minutes ago Exited &lt;span style="color:#f92672"&gt;(&lt;/span&gt;0&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; seconds ago web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker commit ea2 nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sha256:bb388df328ecc33fac02dba69759d5c992a145f650a0e5b20ca29a4b122fa933&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;docker commit命令可以用来提交变更，ea2是container id的前三位，也可以写全；然后跟的是要提交的镜像。这里提交到phalcon这个标签下，以便与原来的区分开。查看所有镜像，发现有两个不同的标签：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx-php-fpm phalcon bb388df328ec &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; seconds ago 364.4 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx-php-fpm latest 4fc9ac9f2945 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; hours ago 228.5 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;采用新镜像来运行，这里要讲程序运行入口改回/start.sh，以便能正常启动Nginx和PHP-FPM：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker rm web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name web -d -t -i nginx-php-fpm:phalcon /start.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deecb19467cda2676b24248e3f55970a2481255c6022a80ffbf5087792ccb559&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deecb19467cd nginx-php-fpm:phalcon &lt;span style="color:#e6db74"&gt;&amp;#34;/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; seconds 80/tcp, 443/tcp web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;入口程序改变了，需要再提交一次变更：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker stop web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;c7600e62733d nginx-php-fpm:phalcon &lt;span style="color:#e6db74"&gt;&amp;#34;/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; seconds ago Exited &lt;span style="color:#f92672"&gt;(&lt;/span&gt;137&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; seconds ago web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker commit c76 nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sha256:1c97ee169a551dd8441f42b40beafd102c71f3e887e2317dc11ce0ef136ceaf0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行最终的镜像：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker rm web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name web -d -t -i nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cb5b0c9e55913a538539e46c53ac7905b21def84a05eb00ef81c4b500853576c&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cb5b0c9e5591 nginx-php-fpm:phalcon &lt;span style="color:#e6db74"&gt;&amp;#34;/start.sh&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; seconds ago Up &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; seconds 80/tcp, 443/tcp web&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;访问http://172.17.0.2/，便可以在页面找到phalcon扩展。&lt;br&gt;&#10;通常我们会将程序和数据分开，挂载外部文件目录到容器里面去：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker stop web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker rm web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;web&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name web -d -t -i -v /home/docker/nginx-php-fpm/src:/var/www/html/ nginx-php-fpm:phalcon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ffd64793fe8e7a2a95b68f514e221b7ec3b6cadfe668c016f55a7bb6d48bc702&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;-v参数可以用来挂载目录或者文件，可以又多个-v参数。&lt;br&gt;&#10;刚才容器里面做的那些已经添加到&lt;a class="link" href="https://github.com/llitllie/nginx-php-fpm-phalcon" target="_blank" rel="noopener"&#10; &gt;Dockerfile里&lt;/a&gt;面去，你直接使用它来构建。&lt;br&gt;&#10;至此Nginx + PHP-FPM + Phalcon镜像构建完成，介绍绍了如何进入容器，提交变更，网络访问和文件挂载。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="http://phusion.github.io/baseimage-docker/" target="_blank" rel="noopener"&#10; &gt;A minimal Ubuntu base image modified for Docker-friendliness&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://hub.docker.com/r/eboraas/phalcon/~/dockerfile/" target="_blank" rel="noopener"&#10; &gt;eboraas/phalcon&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://dockone.io/article/117" target="_blank" rel="noopener"&#10; &gt;基于Docker的PHP开发环境&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.newmediacampaigns.com/blog/docker-for-php-developers" target="_blank" rel="noopener"&#10; &gt;Docker for PHP Developers&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://avnpc.com/pages/build-php-develop-env-by-docker" target="_blank" rel="noopener"&#10; &gt;Docker在PHP项目开发环境中的应用&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/yeasy/docker_practice/blob/master/cases/supervisor.md" target="_blank" rel="noopener"&#10; &gt;使用 Supervisor 来管理进程&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/php-%e6%a1%86%e6%9e%b6phalcon/" target="_blank" rel="noopener"&#10; &gt;PHP C扩展框架Phalcon&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.infoq.com/cn/news/2016/01/Alpine-Linux-5M-Docker" target="_blank" rel="noopener"&#10; &gt;Alpine Linux，一个只有5M的Docker镜像&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Ubuntu 16.04 上安装Docker</title><link>https://courages.us/ubuntu-16-04-%E4%B8%8A%E5%AE%89%E8%A3%85docker/</link><pubDate>Wed, 28 Sep 2016 21:32:11 +0800</pubDate><guid>https://courages.us/ubuntu-16-04-%E4%B8%8A%E5%AE%89%E8%A3%85docker/</guid><description>&lt;p&gt;Docker是一个轻量级的虚拟化容器技术，既可以为不同应用程序提供了隔离空间（内存，资源，网络），又可以将应用程序与环境一起打包，发布到其他机器上，避免环境的差异，这点像&lt;a class="link" href="https://courages.us/windows-8-%e5%ae%89%e8%a3%85vagrant%e5%92%8cvirtualbox/" target="_blank" rel="noopener"&#10; &gt;Vagrant&lt;/a&gt;。 但是，它又与传统的虚拟机不容（如VirtualBox），它的应用程序仍然是跑在宿主机上面的，并且镜像里面通常仅包含所必须的组件而非完整的系统，因此拥有极高的性能。这又有点像Python的Virtual Environment，不过Docker更加强大，本质是是个Linux，可以打包的不同语言的应用程序。&lt;br&gt;&#10;Docker要求linux内核版本大于3.10，可以在通过以下命令查看是否支持&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ uname -r&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4.4.0-38-generic&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;需要先更新以下apt仓库&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt-get update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt-get install apt-transport-https ca-certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;/sell&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;检查以下是否已经创建Docker软件仓库文件,如果没有需要手动创建，并添加以下内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# cat /etc/apt/sources.list.d/docker.list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deb https://apt.dockerproject.org/repo ubuntu-xenial main&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;/sell&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;确认是否配置成功&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# sudo apt-get update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# apt-cache policy docker-engine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker-engine:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Installed: 1.12.1-0~xenial&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Candidate: 1.12.1-0~xenial&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Version table:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; *** 1.12.1-0~xenial &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; https://apt.dockerproject.org/repo ubuntu-xenial/main amd64 Packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; /var/lib/dpkg/status&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1.12.0-0~xenial &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; https://apt.dockerproject.org/repo ubuntu-xenial/main amd64 Packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1.11.2-0~xenial &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; https://apt.dockerproject.org/repo ubuntu-xenial/main amd64 Packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1.11.1-0~xenial &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; https://apt.dockerproject.org/repo ubuntu-xenial/main amd64 Packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1.11.0-0~xenial &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; https://apt.dockerproject.org/repo ubuntu-xenial/main amd64 Packages&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker容器建立在Auf文件系统之上，以便支持将不同的目录挂载到同一虚拟文件系统下面，并设置不同的读写权限。需要安装linux-image-extra：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt-get install linux-image-extra-&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;uname -r&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt; linux-image-extra-virtual&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;/sell&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;现在可以开始安装Docker了：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo apt-get install docker-engine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo service docker start&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;试运行一下：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run hello-world&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hello from Docker!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;This message shows that your installation appears to be working correctly.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;To generate this message, Docker took the following steps:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1. The Docker client contacted the Docker daemon.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2. The Docker daemon pulled the &lt;span style="color:#e6db74"&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt; image from the Docker Hub.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3. The Docker daemon created a new container from that image which runs the&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; executable that produces the output you are currently reading.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4. The Docker daemon streamed that output to the Docker client, which sent it&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; to your terminal.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;To try something more ambitious, you can run an Ubuntu container with:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $ docker run -it ubuntu bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Share images, automate workflows, and more with a free Docker Hub account:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://hub.docker.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For more examples and ideas, visit:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://docs.docker.com/engine/userguide/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你本地没有hello-world这个镜像，它是会自动去Docker官网上下载的。&lt;br&gt;&#10;查看最近运行过的容器，不加参数-l，是查看正在运行的容器&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1931765938dc hello-world &lt;span style="color:#e6db74"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; minutes ago Exited &lt;span style="color:#f92672"&gt;(&lt;/span&gt;0&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; minutes ago suspicious_lichterman&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行镜像的时候也可以指定名称（而不是suspicious_lichterman）&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name hello hello-world&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Hello from Docker!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker ps -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;e4773606e6cf hello-world &lt;span style="color:#e6db74"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; seconds ago Exited &lt;span style="color:#f92672"&gt;(&lt;/span&gt;0&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; seconds ago hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但是再次运行同样名称为hello的容器时会报错&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker run --name hello hello-world&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker: Error response from daemon: Conflict. The name &lt;span style="color:#e6db74"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt; is already in use by container e4773606e6cf4222b786d5301ab38e4dddb90e11a0358f64d33109bf829f0b5a. You have to remove &lt;span style="color:#f92672"&gt;(&lt;/span&gt;or rename&lt;span style="color:#f92672"&gt;)&lt;/span&gt; that container to be able to reuse that name..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;See &lt;span style="color:#e6db74"&gt;&amp;#39;docker run --help&amp;#39;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这时候需要先把旧的给删掉，再运行就不会了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker rm hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过Docker stop停止运行指定容器。&lt;br&gt;&#10;查看本地的Docker镜像&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@thinkpad:~# docker images&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx-php-fpm phalcon 1c97ee169a55 &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; hours ago 364.5 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx-php-fpm latest 4fc9ac9f2945 &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; hours ago 228.5 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ubuntu 16.04 c73a085dc378 &lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; hours ago 127.1 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ubuntu latest c73a085dc378 &lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; hours ago 127.1 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nginx mainline-alpine 00bc1e841a8f &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; days ago 54.21 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mysql 5.7 4b3b6b994512 &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; weeks ago 384.5 MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hello-world latest c54a2cc56cbb &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; weeks ago 1.848 kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里先简单的介绍Docker的安装、运行，后续将介绍Docker命令行交互，网络，文件存储等。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="http://Docker%20Overview" target="_blank" rel="noopener"&#10; &gt;Docker Overview&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.infoq.com/cn/articles/docker-containers" target="_blank" rel="noopener"&#10; &gt;Docker：利用Linux容器实现可移植的应用部署&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://docs.docker.com/engine/installation/linux/ubuntulinux/" target="_blank" rel="noopener"&#10; &gt;Installation&lt;br&gt;&#10;on Ubuntu&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.infoq.com/cn/news/2013/04/Docker" target="_blank" rel="noopener"&#10; &gt;Docker：具备一致性的自动化软件部署&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.gitbook.com/book/yeasy/docker_practice/details" target="_blank" rel="noopener"&#10; &gt;Docker — 从入门到实践&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://segmentfault.com/a/1190000000448808" target="_blank" rel="noopener"&#10; &gt;Docker简介与入门&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.infoq.com/cn/articles/analysis-of-docker-file-system-aufs-and-devicemapper" target="_blank" rel="noopener"&#10; &gt;剖析Docker文件系统：Aufs与Devicemapper&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://stackoverflow.com/questions/21889053/what-is-the-runtime-performance-cost-of-a-docker-container" target="_blank" rel="noopener"&#10; &gt;What is the runtime performance cost of a Docker container&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.slideshare.net/strbalaji/docker-26650285?next_slideshow=1" target="_blank" rel="noopener"&#10; &gt;Docker – The Linux Container&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://betacz.com/2014/05/21/vagrant-met-docker-2/" target="_blank" rel="noopener"&#10; &gt;当流浪者(Vagrant)遇见码头工人(Docker): 实战&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>