背景

容器化部署是现在进行时,开源应用大多数支持容器化部署
在少量机器的场景下往往采用docker cli 和 docker-compose管理,进行“单机试管理”
机器稍多点会采用Docker Swarm群集的方式,毕竟k8s稍重
如果有更多的机器情况下一般会采用k8s的方式
在个人、创业公司、小团队的场景下我们往往在多个云、家里、vps上拥有少量虚拟机服务器,这些服务器上都运行了docker实例
虽然我们也可以用公网vpn、zerotier等方式打通各个地域的机器形成一个内网,从而构建“群集”,但实际情况是没那么多带宽,从而无法“负载均衡”,所以实际的使用还是独立使用
受限制于公网带宽很小,只能独立使用
我们也拥有一些4G移动流量接入这种EDGE边缘场景的情况,这些IoT上也运行着Docker实例
那么这些NAT内网环境下的Docker实例,公网IP环境下的Docker实例,是否能集中管理?
当然可以,用Portainer就挺方便

用Portainer作为Docker实例管理平台

Portainer server主控安装

选一个7×24小时且有公网IP的节点运行Portainer server主控

docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /data/appdata/portainer:/data portainer/portainer

9000端口为web管理界面端口
8000端口为Agent接入端口
这2个端口公网IP防火墙都必须放行

浏览器打开web管理界面
http://Portainer server主控公网IP:9000

初次访问设置一个密码,设置密码后需要选择连接docker的方式
选第一个Local 然后点击Connect
默认进入Home菜单,点击这个Local本地docker实例进入其他管理

Portainer官方安装手册参考

配置https nginx代理(可选)

http://你的公网IP:9000 默认没有https不安全
规划一个域名用于https访问例如https://portainer.iamle.com
用nginx作为接入反向代理到 http://portainerip:9000
下面为示例nginx portainer配置(其中包含需要的websocket proxy)

# portainer.iamle.com.conf
map $http_upgrade $connection_upgrade {
    default Upgrade;
    ''      close;
}
upstream portainer {
    server 127.0.0.1:9000;
}
server {
        listen       80;
        server_name portainer.iamle.com;
        return      301 https://$server_name$request_uri;
}
server {

                listen 443 ssl http2;
        server_name portainer.iamle.com;

                ssl_certificate         ssl/iamle.com.cer;
                ssl_certificate_key     ssl/iamle.com.key;
                #ssl_session_cache           shared:SSL:10m;
                #ssl_session_timeout         10m;
                #ssl_session_tickets         off;

                ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
                ssl_ciphers         HIGH:!aNULL:!MD5:!EXPORT56:!EXP;
                ssl_prefer_server_ciphers on;

        location / {
                    proxy_set_header Host              $host;
                    proxy_set_header X-Forwarded-Proto $scheme;
                    proxy_set_header X-Forwarded-Port  $server_port;
                    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
                    proxy_set_header X-Real-IP         $remote_addr;
                    proxy_set_header X-Request-Id $request_id;
                    proxy_set_header Upgrade           $http_upgrade;
                    proxy_set_header Connection        $connection_upgrade;
                    proxy_read_timeout 60m;
                    proxy_send_timeout 60m;
                    proxy_http_version 1.1;
                    proxy_pass http://portainer;
                    break;
        }


        error_log   /data/logs/portainer.iamle.com-error.log;
        access_log  /data/logs/portainer.iamle.com.log access;

}

配置一个NAT内网Agent客户端

前面我们已经配置好一个具有公网IP的Portainer管理控制节点
那么现在把内网(NAT、IoT)、公有云、vps等运行的Docker实例来接入控制节点管理

一图胜千言,官方介绍图

图中这个Portainer管理了2个内网的Agent
其中一个是个Swarm群集,另外一个是个单机

Portainer server上增加一个Edge Agent

Endpoints菜单 》 Add endpoint 》 Edge Agent

Name:为自定义
Portainer server URL:默认为当前Portainer server ip (如果用nginx配置了https可以使用https不加端口号)
》 Add endpoint

增加端点后出现

部署客户端agent 有2种选择 Standalone 和 Swarm
如果已经组过Swarm那么选Swarm,默认就是Standalone
先点击 “Copy command” 复制命令,在Agent客户端去执行
Public IP: 如果有可以设置,这样在以后部署了docker容器暴露的端口可以自动生成url

需要被管理的Docker实例客户端机

在被管理的客户端终端上执行(内网(NAT、IOT)、公网环境都可以,只要能连接上我们的Portainer server)
本例内网1台ip为 192.168.0.8的机器

docker run -d -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes -v /:/host --restart always -e EDGE=1 -e EDGE_ID=6ad0f1ff-6fea-4710-97e2-513ef1066fd8 -e CAP_HOST_MANAGEMENT=1 -p 8000:80 -v portainer_agent_data:/data --name portainer_edge_agent portainer/agent:1.5.1

访问 http://192.168.0.8:8000(如果有公网ip用公网ip)
打开后会有个输入框
输入上一步获得的Join token
点击Submit 出现 Agent setup OK. You can close this page. 代表完成agent接入

回到 Portainer server管理界面等待上线

点击 iamle-lan-01 等待几秒钟

这样我们就可以管理多个docker实例了

贴士

  • 如果agent运行不起来,无限重启
    需要根据docker logs portainer_edge_agent 获取到的错误信息排查, 官方github issue是个好去处
    另外发现2019年10月19日16:55:01 pull 下来的portainer/agent:latest 也运行不起来 改为 portainer/agent:1.5.1正常

  • Stacks粘贴docker-compose.yml进来后一直报version版本不对
    目前只支持version 2 改为2即可

参考

Portainer Edge Agent 官方发布
Portainer内网边缘节点配置说明书PDF

副标
Dockerize your Vue Application
dockerfile Vue example
docker Vue example
Vue应用docker容器化打包

docker忽略文件

.dockerignore

www.conf

Dockerfile

副标
Dockerize your Golang Application
dockerfile Golang example
docker golang example
Go应用docker容器化打包

Dockerfile

基础镜像使用aline
使用docker的多阶段构建

Dockerfile

docker-compose.yml

副标
Dockerize your Python Application
dockerfile python example
dockerfile python flask example

flask框架为例

Dockerfile

本文提供
Windows系统下使用laradock作为开发运行环境, PhpStorm作为开发IDE, 如何配置xdebug 断点调试
OSX系统下使用laradock作为开发运行环境, PhpStorm作为开发IDE, 如何配置xdebug 断点调试

laradock中php-fpm 的xdebug.ini配置

laradock/php-fpm/xdebug.ini
如果是Windows系统则改为

如果是OSX系统则改为

xdebug.ini文件中其他参数不用动
xdebug.remote_host参数设置的是xdebug服务器的地址,这里实际上是“母鸡”也就是phpstorm的网络地址
xdebug.remote_connect_back这个参数如果为1表示根据请求来源“remote_host”,来发起调试,在docker环境下有网络nat所以不会成功,这个参数的改为0

phpstorm的配置

设置中> Languages & Frameworks > PHP
Debug 默认参数可以不动
Servers 中Name: laradock Host:你的网址 Port:80 Debugger:Xdebug
勾选 “Use path mappings” 把项目目录和laradock中 /var/www/你的项目 进行目录映射
phpstorm的xdebug配置不在累述,可以参见laradock http://laradock.io/documentation/#install-xdebug
laradock + phpstorm配置xdebug不成功多半是xdebug.remote_connect_back没设置为0

前言

组织的容器支持docker-compose部署
组织的容器支持kubernets部署
以php框架thinkphp为示例,演示php项目的kubernets部署
多容器方式(3容器)分别为:appphp(php代码)、openresty(nginx webserver),php-fpm(php的运行环境)
dockerfile 和 yaml文件
docker iamges仓库

PHP项目在Docker中如何部署运行?

PHP应用的运行方式

PHP应用的运行方式一般有
Apache mod_php 模式、Nginx(FastCgi)+PHP-FPM模式、Swoole常驻内存Daemon模式

Docker单容器

Apache mod_php 模式和Swoole常驻内存Daemon模式本身就是单程序,那么在Docker中入口运行程序直接为应用程序即可

Nginx(FastCgi)+PHP-FPM模式需要nginx和php-fpm 2个程序
这样Docker中就需要运行多个程序,需要有进程守护类软件来运行多个程序,那么可以参考如何在一个Docker中运行多个程序进程
推荐使用s6-overlay

Docker Hub中PHP官方镜像包已经包括Apache mod_php 模式的镜像包,Kubernets官方PHP项目实例GuestBook中就是采用这种模式的镜像包

Docker多容器配合

Docker官方倡导容器单一职责,也就是一个容器只运行一个程序
那么Nginx(FastCgi)+PHP-FPM模式就需要2个容器配合编排工作,再加上如果把PHP代码再独立成一个Docker镜像,那么就是3容器配合编排工作
所以下面就是以PHP项目采用多个Docker镜像的方式再Kubernets平台部署的范例

kubernets(k8s)部署运行

思路说明
容器共有3个,① appphp(wwek/k8s-php-thinkphp-hello:app-v1)php代码容器、② php-fpm(wwek/k8s-php-thinkphp-hello:php-fpm-7.2) 、③ openresty(wwek/k8s-php-thinkphp-hello:openresty)
apphp、php-fpm、openresty三个容器都在一个Pod(8s-php-thinkphp-hello)中
appphp容器作为initContainers初始化容器使用
挂载了一个叫做wwwroot的volume,类型为emptyDir,临时卷
initContainers初始化容器的时候会把php代码复制到wwwroot(volume)中
php-fpm和openresty都挂载wwwroot(volume)
openresty的upstream php 使用域名php-fpm
使用hostAliases把域名php-fpm解析为127.0.0.1(在同一个Pod中网络是共享的,所以用127.0.0.1)

具体的yaml文件

把 k8sphpthinkphp.com hosts解析到Ingress 的ip
然后浏览器

访问 http://k8sphpthinkphp.com/ 可以看到thinkphp的欢迎页面

访问 http://k8sphpthinkphp.com/phpinfo.php 可以看到phpinfo信息

如果没有ingress请自行修改service的type为 NodePort 使用节点的ip和端口访问

docker-compose部署运行

一套打包好的业务PHP Docker业务镜像也可以用docker-compose部署,这样方便了本地的开发调试使用

直接up方式,直接pull已经build好的docker images

本地build方式

浏览器 访问 http://127.0.0.1 访问 http://127.0.0.1/phpinfo.php

代码

所有配置范例代码已经托管到github
k8s-php-thinkphp-hello