(Translated by https://www.hiragana.jp/)
GitHub - ti0s/docker-remote-api-php
Skip to content

ti0s/docker-remote-api-php

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 

Repository files navigation

docker-remote-api-php

かんかたぶん档🔗:https://docs.docker.com/engine/api/ 以通过 docker version查看 Engine: API version 个人とうぜん ふく务器きゃく户端1.4版本はんぽん注意ちゅうい版本はんぽん不同ふどう,さつ不同ふどう基本きほんじょう一个小版本一个手册 わが宣布せんぷcurl就是わがだい哥 👍 ぜんはし来着らいちゃくxpp

search the containers

curl http://192.168.21.131:2375/containers/json

create one container

  • create.json

https://docs.docker.com/engine/api/v1.40/#operation/ContainerCreate

curl -v -X POST -H "Content-Type: application/json"  http://192.168.21.131:2375/containers/create?name=dvwa -d '{"Image": "astronaut1712/dvwa:latest", "HostConfig": {"NetworkMode": "bridge","PortBindings": {"80/tcp": [{"HostPort": "3080"}]}}}'

start the container

curl -v -X POST http://192.168.21.131:2375/containers/dvwa/start

stop the container

curl -v --raw -X POST http://192.168.21.131:2375/containers/dvwa/stop

delete the container

 curl -v -X DELETE http://192.168.21.131:2375/containers/dvwa

php あずか docker remote api

└─fe1w0
        class.php
        config.php
        curl.php
        docker.php
        error.php
        error1.html
        error2.html
        error3.html
        error4.html
        index.css
        index.html

其中重要じゅうようてきclass.php、curl.php、config.php、docker.php

  • class.php
<?php
class docker{
    public $ip_url;    # http://192.168.21.131:2375 config.php
    public $image_name;
    public $container_name;
    public $container_port;
    public $time;
    public $search_url;
    public $create_url;
    public $start_url;
    public $stop_url;   
    public $delete_url;
    public $data_string;
    public $max_number;  # 容器ようきてき最大さいだい数量すうりょう config.php
    public $number;
    public $arr_container;
    public $port_pool;
    public $current_ports;
    public $error_location;

    function __construct($ip_url="",$image_name="",$container_name="",$container_port="",$time="",$max_number=30,$port_pool,$error_location)
    {
        $this->ip_url =$ip_url;
        $this->image_name = $image_name;
        $this->container_name = $container_name;
        $this->container_port = $container_port;
        $this->max_number = $max_number;
        $this->arr_container=array();
        $this->current_ports=array();
        $this->port_pool=$port_pool; //はしこういけゆかり外部がいぶ设置
        $this->number=0;
        $this->error_location = $error_location;

        $parsed = date_parse($time);
        $this->time= $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];

        $this->search_url = sprintf('%s/containers/json?all=1',$this->ip_url);# get
    }

    function geturl($url){
        # はつはじめ
        $headerArray =array("Content-type:application/json;","Accept:application/json");
        $ch = curl_init();
        
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch,CURLOPT_TIMEOUT,500);
        curl_setopt($ch,CURLOPT_URL,$url); # url 为apiてきurl
        curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
        #curl_setopt($ch, CURLOPT_HEADER, true);
        $output = curl_exec($ch);
        curl_close($ch);
    
        # json 转为すう组 $res
        $output = json_decode($output,true);
        return $output;
    }

    
    function posturl($url,$data_string=""){
        #$data_string = json_encode($requestData);
        #var_dump($data_string);
        $ch = curl_init();
        $headerArray = array('Content-Type: application/json', 'Content-Length: '.strlen($data_string));
    
        curl_setopt($ch,CURLOPT_URL,$url);
        #curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
        $output = curl_exec($ch);
        curl_close($ch);
    
        #$output = json_decode($output,true);
        return $output;
    }


    function deleteurl($url){
        $ch = curl_init();
    
        curl_setopt($ch, CURLOPT_URL, $url);
        #curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        $output = curl_exec($ch);
        curl_close($ch);
        
        #$output = json_decode($output,true);
        return $output;
    }



    function number_container()
    {
        $this->arr_container = $this->geturl($this->search_url);
        $this->number = count($this->arr_container,0);
    }

    # いた一个相对随机的端口
    function Random_port()
    {
        # 暂时使用しよう垃圾いちてんてき 伪随つくえはしこう
        $max = end($this->port_pool);
        $min = reset($this->port_pool);
        $port = mt_rand($min,$max);
        return $port;
    }
    # 获取とうぜん容器ようきてきはし口数くちかず
    function get_port_array()
    {
        $this->arr_container = $this->geturl($this->search_url);
        #var_dump($this->arr_container);
        $this->number = count($this->arr_container,0);
        $i = range(0,$this->number-1);
        if($this->number != 0)
        {
            foreach($i as $nn)
            {
                $this->current_ports[$nn] = $this->arr_container[$nn]["Ports"][1]["PublicPort"];
            }
        }

    }

    # 迭代确定さい终端こう
    function get_port()
    {   
        $booL = true;
        $Random_port =$this->Random_port();
        $this->get_port_array();
        while(true){
            foreach($this->current_ports as $port)
            {
                if($port == $Random_port)
                {
                    $booL= false;
                }
            }
            if(!$booL){
                $this->get_port();
            }
            else
            {
                $this->container_port = $Random_port;
                #echo("[*] Container_port: ".$this->container_port."\n");
                break;
            }
        }

    }
    # じゅうしん载参すう



    function create_container(){
        $res = $this->posturl($this->create_url,$this->data_string);
        echo("[*] create container:");
        echo('Request: curl -v -X POST -H "Content-Type: application/json" '.$this->create_url.' -d \''. $this->data_string.'\''."<br>");
        echo("Response: ".$res."<br>");
    }

    function start_container(){
        $res =  $this->posturl($this->start_url);
        echo("[*] start container:");
        echo('Request: curl -v -X POST '.$this->start_url."<br>");
        echo("Response: ".$res."<br>");
    }

    function stop_container(){
        $res = $this->posturl($this->stop_url);
        echo("[*] stop container:");
        echo('Request: curl -v -X POST '.$this->stop_url."<br>");
        echo("Response: ".$res."<br>");
    }

    function delete_container(){
        $res = $this->deleteurl($this->delete_url);
        echo("[*] delete container:");
        echo('Request: curl -v -X DELETE '.$this->delete_url."<br>");
        echo("Response: ".$res."<br>");
    }

    function ready()
    {
        $this->number_container();
        $this->reset();
        if($this->number < $this->max_number)
        {
            return true;
        }
        else{
            return false;
        }


    }

    function reset()
    {
        if(!$this->container_name  and  !$this->container_port)
        {
            $this->get_port(); // container_port
            //container_name
            $pre_container_name=time();
            $this->container_name = $pre_container_name.$this->container_port; 
        }
        $this->create_url = sprintf('%s/containers/create?name=%s',$this->ip_url,$this->container_name); #post
        $this->start_url = sprintf('%s/containers/%s/start',$this->ip_url,$this->container_name); #post
        $this->stop_url = sprintf('%s/containers/%s/stop?t=%s',$this->ip_url,$this->container_name,$this->time); #post
        $this->delete_url = sprintf('%s/containers/%s',$this->ip_url,$this->container_name); #delete
        $this->data_string = sprintf( '{"Image": "%s","HostConfig": {"NetworkMode": "bridge","PortBindings": {"80/tcp": [{"HostPort": "%s"}]}}}',$this->image_name,$this->container_port);
    }

    function docker(){
        $this->create_container($this->create_url,$this->data_string);
        $this->start_container($this->start_url);
        $this->stop_container($this->stop_url);
        //$this->delete_container($this->delete_url);
    }

}

?>
  • curl.php
<?php 
@include_once('config.php');
@include_once('class.php');

$time=$_POST['TTL'];
$image_name=$_POST['image_name'];

 
/* $image_name="dvwa";
$time="00:01:00";
 */

/*
if(isset($_SERVER['HTTP_REFERER'])) {
    if($_SERVER['HTTP_REFERER']!== $refer_url )
    {   
        $string = sprintf("<script>location.href='%s?error=1';</script>",$error_location); // 错误类型 1 $_SERVER['HTTP_REFERER'])错误 ,とべ转到login.php
        echo($string);
    }
}
else{
    $string = sprintf("<script>location.href='%s?error=2';</script>",$error_location);  // 错误类型 2  $_SERVER['HTTP_REFERER'])かけしょう ,とべ转到login.php
}
*/

function check_images($data,$images_array)
{
    if($images_array[$data]){
        return false;
    }
    else{
        return true;
    }
}
function check_time($time)
{  
    $parsed = strtotime($time);
    return empty($parsed);
}

## docker

if( empty($image_name) or empty($time) or check_images($image_name,$images_array) or check_time($time)){  
    $string = sprintf("<script>location.href='%s?error=4';</script>",$error_location);
    echo($string);       //错误类型 4 docker 页面さんすうかけすくなある错误,とべ转到靶机请求页面
}
else{
    $image_name = $images_array[$image_name];
    $docker = new docker($ip_url,$image_name,$container_name="",$container_port="",$time,$max_number,$port_pool,$error_location);
    $BOOL = $docker->ready();
    if($BOOL)
    {
        // とべ转到成功せいこう页面
        $string = sprintf("<script>location.href='http://192.168.21.131:%s';</script>",$docker->container_port);
        echo $string;
        //image_name   container_name  container_port time
        $shell = sprintf("php docker.php %s %s %s %s >/dev/null &",$image_name,$docker->container_name,$docker->container_port,$time);
        var_dump($shell);
        shell_exec($shell);
    }
    else{
        $string = sprintf("<script>location.href='%s?error=3';</script>",$docker->error_location);
        echo($string);    //错误类型 3 容器ようき达到上限じょうげん,とべ转到同一どういつてき错误页面
    }
}

?>
  • config.php
<?php
$ip_url = 'http://192.168.21.131:2375'; // docker remote api 
$max_number = 20;   // 最大さいだい靶机数量すうりょう
$port_pool = range(4000,4300);  //はしこう
$error_location = "http://localhost/docker/fe1w0/error.php"; //报错页面  http://202.119.201.197:2000/docker/error.php
$refer_url='http://localhost/docker/fe1w0'; // まこと许的refer_url
$login_url='http://localhost';  // とう录页めん
$images_array=array("dvwa"=>"astronaut1712/dvwa:latest","sqlilabs"=>"c0ny1/sqli-labs:0.1");
?>
  • docker.php
<?php 
@include_once("config.php");
@include_once("class.php");

$docker_parameter = $argv;
var_dump($docker_parameter);

$image_name = $docker_parameter[1];
$container_name = $docker_parameter[2];
$container_port = $docker_parameter[3];
$time = $docker_parameter[4];

$Docker = new docker($ip_url,$image_name,$container_name,$container_port,$time,$max_number,$port_pool,$error_location);
$Docker->reset();
$Docker->docker();
?>

phpあずかてい

目前もくぜんぐういたてき最大さいだいてき难点

两种おもえ

  • php のうひかえせいdocker stop and delete
  • crontab 别人说,可能かのう太合たいごう

docker 远程api ひかえせい stop 、delete

githubじょうてきしょう关讨论

moby/moby#1905

ざい1.4てきぶん档中わが们可以看いたapiゆうStopTimeout这个さんすう,ただしかいてきざい实际使用しようちゅう,并没有效ゆうこうはて(也可能かのうわが设置错了)

image-20200722125449814

以下いかわが尝试てき命令めいれい:

curl -v -X POST -H "Content-Type: application/json http://192.168.21.131:2375/containers/create?name=dvwa -d '{"Image": "astronaut1712/dvwa:latest","HostConfig": {"NetworkMode": "bridge","StopSignal": "SIGTERM","StopTimeout":30,"PortBindings": {"80/tcp": [{"HostPort": "3080"}]}}}'

ただしざいwaitこうのう中有ちゅうう一个起到延时功能的参数,说明如下:

参考さんこう链接:https://docker-php.readthedocs.io/en/latest/cookbook/container-run/#waiting-for-the-container-to-end

image-20200722141740320

おさむあらためphpだい

image-20200722141912689

执行结果

[*] create container:
Request: curl -v -X POST -H "Content-Type: application/json" http://192.168.21.131:2375/containers/create?name=dvwa -d '{"Image": "astronaut1712/dvwa:latest","HostConfig": {"NetworkMode": "bridge","PortBindings": {"80/tcp": [{"HostPort": "3080"}]}}}'
Response: HTTP/1.1 201 Created
Api-Version: 1.40
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.12 (linux)
Date: Wed, 22 Jul 2020 06:15:18 GMT
Content-Length: 88

{"Id":"9a65141c4191505094838d91c5f537744e18a795494c480199f6598951102fa8","Warnings":[]}

[*] start container:
Request: curl -v -X POST http://192.168.21.131:2375/containers/dvwa/start
Response: HTTP/1.1 204 No Content
Api-Version: 1.40
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.12 (linux)
Date: Wed, 22 Jul 2020 06:15:19 GMT

[*] stop container:
Request: curl -v -X POST http://192.168.21.131:2375/containers/dvwa/stop?t=30
Response: HTTP/1.1 204 No Content
Api-Version: 1.40
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.12 (linux)
Date: Wed, 22 Jul 2020 06:15:50 GMT

[*] delete container:
Request: curl -v -X DELETE http://192.168.21.131:2375/containers/dvwa
Response: HTTP/1.1 204 No Content
Api-Version: 1.40
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.12 (linux)
Date: Wed, 22 Jul 2020 06:15:50 GMT

[Finished in 32.2s]

phpあずか容器ようき数量すうりょうひかえせい

利用りよう查询到てき容器ようきしんいきらいかい决该问题

    # 
    function number_container()
    {
        $res = $this->geturl($this->search_url);
        $number = count($res,0);//count()ちゅうてき二个参数为0时,统计だいいち维度てき所有しょゆう元素げんそ,为1时循环统计遍历所有しょゆう元素げんそ
        return $number;
    }
/*

省略しょうりゃくちゅう间的だい

*/

    function docker(){
        $number = $this->number_container();
        if($number < $this->max_number)
        {
            $this->create_container($this->create_url,$this->data_string);
            $this->start_container($this->start_url);
            $this->stop_container($this->stop_url);
            $this->delete_container($this->delete_url);
        }
        else{
            die("[*] 容器ようき数量すうりょうやめ经达到最大さいだい值,请稍きさき尝试");
        }
    }

php あずかはしこう转发

はしこう

はしこう大小だいしょう[5000-6000],这个よし配置はいちぶんけんひかえせい

如:

  • config.php
<?php
$ip_url = 'http://192.168.21.131:2375';
$max_number = 3;
$port_pool = range(4000,4300);
?>
  • docker.php节选
class docker{
    /*
    省略しょうりゃく
    */
    public $port_pool;
    
    function __construct($ip_url="",$image_name="",$container_name="",$container_port="",$time="",$max_number=30,$port_pool)
    {
      	 /*
   		 省略しょうりゃく
    	 */
        $this->port_pool=$port_pool; //はしこういけゆかり外部がいぶ设置
        /*
   		 省略しょうりゃく
    	 */
    }
 /*
省略しょうりゃく
*/ 
}        

统计处于开启じょう态容てきはしこう

  • おもえ
  1. 5000~6000これ间随つくえ挑选いち个端こう port_A
  2. 读取containerてきはしこうしんいき,并用すう保存ほぞんらい port_B
  3. しゃ较, わかport_A 不在ふざいport_B なか,则port_Aさく正常せいじょうてきはしこう;はんこれ,退すさかいいた第一步だいいっぽ,じゅうしん执行,ちょくいたゆう正常せいじょうてきはしこう现。
  • 核心かくしんだい
    # いた一个相对随机的端口
    function Random_port()
    {
        # 暂时使用しよう垃圾いちてんてき 伪随つくえはしこう
        $max = end($this->port_pool);
        $min = reset($this->port_pool);
        $port = mt_rand($min,$max);
        return $port;
    }
    # 获取とうぜん容器ようきてきはし口数くちかず
    function get_port_array()
    {
        $this->arr_container = $this->geturl($this->search_url);
        $this->number = count($this->arr_container,0);
        $i = range(0,$this->number-1);
        foreach($i as $nn)
        {
            $this->current_ports[$nn] = $this->arr_container[$nn]["Ports"][1]["PublicPort"];
        }

    }



    # 迭代确定さい终端こう
    function get_port()
    {   
        $booL = true;
        $Random_port =$this->Random_port();
        $this->get_port_array();
        while(true){
            foreach($this->current_ports as $port)
            {
                if($port == $Random_port)
                {
                    $booL= false;
                }
            }
            if(!$booL){
                $this->get_port();
            }
            else
            {
                $this->container_port = $Random_port;
                echo("[*] Container_port: ".$this->container_port."\n");
                break;
            }
        }

    }
    # じゅうしん载参すう
    function reset()
    {
        $this->data_string = sprintf( '{"Image": "%s","HostConfig": {"NetworkMode": "bridge","PortBindings": {"80/tcp": [{"HostPort": "%s"}]}}}',$this->image_name,$this->container_port);
    }

线程 ある 进程

Q:apiきゃく户端为什么需要じゅよう线程ある进程。

A:以下いか个人理解りかい

とうphp脚本きゃくほんぼつゆう设置线程あるぼつゆう使用しよう进程方式ほうしき启动时,性能せいのうこう虑,ちゅう间器かいゆう响应时间设定,ただし响应ちょう时时,则认为目的もくてきふく务器ゆう问题,そくじょう态为504错误。而多线程てき设定ある进程てき方式ほうしき,かいこう虑响应时间问题,ちょく达结たば。此外,ざいまえいち种情况中,全部ぜんぶ执行ざい以输,而在だい种情况中,ずい进展いち步步ほほ输出。而我てきだい码(おこりはつてきだい码),也遇いた这个问题,とう运行いたdocker()函数かんすう时,需要じゅようとうまち较长てきとうまち时间,如30ふん钟,毫不犹豫就是504报错。所以ゆえん需要じゅよう线程ある进程。

Q:如何いか实现?

A:

image-20200723184832220

回答かいとう参考さんこう此链せっ https://www.zhihu.com/question/31893506/answer/53797159 作者さくしゃじょ汉彬

とうせい如前辈,ざい这么长的时间だんさと,如何いか确保ちち进程()还在进行工作こうさく,这是较难确定てき,ただし对于わが而言きゅうゆうがく习价值。

线程 尝试

がく习链せっ:

【Multi-Threading in PHP with pthreads】

https://gist.github.com/krakjoe/6437782 原文げんぶん

https://download.csdn.net/download/tianhuimin/6407035 为上いちへんてきこぼしただし惜没csdn币¥

https://blog.csdn.net/u010433704/article/details/92795346 free 译文

https://www.cnblogs.com/zhenbianshu/p/7978835.html 实例

https://www.php.net/manual/zh/book.pthreads.php PHPしゅさつ

http://www.netkiller.cn/journal/php.thread.html 推荐

进程 尝试

实话实说,开启いち个新てきshell进程,并在さとめん运行php脚本きゃくほんてき方式ほうしき, 个人较推荐,就是ようひかえせいこうさんすう,以免直接ちょくせつ构造webshell。

だい致思利用りようshell_exec()らい实现异步执行,どう时将输出导向/dev/null,并在はたとう前作ぜんさく业(docker.php)いたとうまえてきshellてききさきだい执行。

だい致代码

  • curl.php
if( empty($image_name) or empty($time) or check_images($image_name,$images_array) or check_time($time)){  
    $string = sprintf("<script>location.href='%s?error=4';</script>",$error_location);
    echo($string);       //错误类型 4 docker 页面さんすうかけすくなある错误,とべ转到靶机请求页面
}
else{
    $image_name = $images_array[$image_name];
    $docker = new docker($ip_url,$image_name,$container_name="",$container_port="",$time,$max_number,$port_pool,$error_location);
    $BOOL = $docker->ready();
    if($BOOL)
    {
        // とべ转到成功せいこう页面
        $string = sprintf("<script>location.href='http://192.168.21.131:%s';</script>",$docker->container_port);
        echo $string;
        //image_name   container_name  container_port time
        $shell = sprintf("php docker.php %s %s %s %s >/dev/null &",$image_name,$docker->container_name,$docker->container_port,$time);
        var_dump($shell);
        shell_exec($shell);
    }
    else{
        $string = sprintf("<script>location.href='%s?error=3';</script>",$docker->error_location);
        echo($string);    //错误类型 3 容器ようき达到上限じょうげん,とべ转到同一どういつてき错误页面
    }
}
  • docker.php
<?php 
@include_once("config.php");
@include_once("class.php");

$docker_parameter = $argv;
var_dump($docker_parameter);

$image_name = $docker_parameter[1];
$container_name = $docker_parameter[2];
$container_port = $docker_parameter[3];
$time = $docker_parameter[4];

$Docker = new docker($ip_url,$image_name,$container_name,$container_port,$time,$max_number,$port_pool,$error_location);
$Docker->reset();
$Docker->docker();
?>

きさき计与そうほう

😓いち开始,打算ださん远程ひかえせいzstackらい创建销毁ぬしつくえ,虽然かん网上ゆう这一部分ぶぶん资料,ただしくだりせいてき方案ほうあん实现おこりらい难度还是だかかずろう商量しょうりょうきさき,さいようざいzstack开启いち个dockerうんぬしつくえ,并用remote apiらい实现容器ようきてき创建销毁,目前もくぜんらい实现せいようだか很多,ただし安全あんぜんせい也是个燃まゆきゅう[Docker 2375 はしこういれおかせふく务器 ],这还さん脚本きゃくほんちゅうてき问题(暂时ざいdockerてき方法ほうほう中有ちゅうういちcheck函数かんすう,以备きさき研究けんきゅう)。此外,ゆうそら着手ちゃくしゅがくswoole

Orz,丢人てき

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 52.1%
  • CSS 25.3%
  • HTML 22.6%