官 方 文 档🔗:https://docs.docker.com/engine/api/可 以通过docker version
查看 Engine: API version 个人当 前 服 务器和 客 户端都 是 1.4版本 需注意 版本 不同 ,手 册 也不同 ,基本 上 一个小版本一个手册我 宣布 curl
就是我 大 哥 👍前 端 来着 xpp
curl http://192.168.21.131:2375/containers/json
- 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"}]}}}'
curl -v -X POST http://192.168.21.131:2375/containers/dvwa/start
curl -v --raw -X POST http://192.168.21.131:2375/containers/dvwa/stop
curl -v -X DELETE http://192.168.21.131:2375/containers/dvwa
└─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
能 控 制 docker stop and delete- crontab
看 别人说,可能 不 太合 适
github
上 的 相 关讨论
StopTimeout
这个
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
[*] 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]
#
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("[*] 容器 数量 已 经达到最大 值,请稍后 尝试");
}
}
[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; //端 口 池 由 外部 设置
/*
省略
*/
}
/*
省略
*/
}
思 路
- 从
5000~6000
之 间随机 挑选一 个端口 port_A - 读取container
的 端 口 信 息 ,并用数 组保存 下 来 port_B 二 者 比 较,若 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:
Q:
A:
此
回答 参考 此链接 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 实例
实话实说,开启
shell_exec()
/dev/null
,并在docker.php
)
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();
?>
😓check
swoole
。
Orz,丢人