先说说原理,其实很简单,docker提供了一套socket接口,基于unix套接字,只要实现nginx能经过socket访问docker基本就上就OK了。html
因而想到了nginx + lua,因为服务器上有openresty,直接就拿来用了,经过lua-resty-http 模块,使用unix套接字访问docker的接口,没想到还真能够nginx
代码很简单angularjs
docker.luaweb
local http = require "resty.http" local _M = {} -- 运行docker remote api, function do_docker_cmd(uri, is_post) local httpc = http.new() local method = "GET" if is_post == true then method = "POST" end httpc:connect('unix:/var/run/docker.sock') local res, err = httpc:request({ path = 'http://localhost' .. uri, method = method, headers = { ["Host"] = "localhost", ["Accept"] = "application/json", ["Accept-Encoding"] = "utf-8" } }) if err then return nil, err end httpc:set_keepalive(60) if res.status == 500 then ngx.log(ngx.ALERT, res.body) end return res, nil end -- 获取全部容器 function _M.index() local resp, err = do_docker_cmd('/containers/json'); if err then ngx.say(err); return end ngx.say(resp:read_body()); end -- 中止容器 function _M.stop() local id = ngx.var.arg_id local resp, err = do_docker_cmd('/containers/' .. id .. '/stop', true); if err then ngx.say(err); return end ngx.say(resp:read_body()); end -- 重启容器 function _M.restart() local id = ngx.var.arg_id local resp, err = do_docker_cmd('/containers/' .. id .. '/restart', true); if err then ngx.say(err); return end ngx.say(resp:read_body()); end
若是连不上,那多是docker.sock文件没有权限,chmod 给一下权限就好了,或者把nginx 的用户改一下也行docker
剩下的就是写一个简单的页面 html + angular1,把容器都读出来,显示容器信息了,效果图以下:json
我这里,只有两个操做,一个是中止 一个是重启,看日志功能没时间作api
angularjs服务器
function loadContainer() { $http.get('/app/docker').then(function (res) { $scope.containers = res.data }) } $scope.stopContainer = function(item) { $http.get('/app/docker/stop', {params: {id: item.Id}}).then(function(res) { loadContainer(); }) } $scope.restartContainer = function(item) { $http.get('/app/docker/restart', {params: {id: item.Id}}).then(function(res) { loadContainer(); }) } $scope.showContainers = function() { var views = document.getElementsByClassName('ui-view'); for (var i = 0; i < views.length; i++) { views[i].setAttribute('class', 'ng-hide ui-view'); } document.getElementById('containers').setAttribute('class', 'ui-view') loadContainer(); }
htmlapp
<div id="containers" class="ng-hide ui-view"> <div ui-view="list-c" class="console-container ng-scope" ng-animate="{enter:'fade-enter'}"> <div class="console-title ng-scope"> <div class="pull-left"> <h5>容器列表</h5> <ul class="nav nav-pills"> <!-- ngRepeat: item in vm.region --> <li ng-repeat="item in vm.region" ng-class="{'active':vm.selectedRegion==item.region}" class="ng-scope active"> </li><!-- end ngRepeat: item in vm.region --> </ul> </div> </div> <!-- ngIf: !vm.initial --> <div class="ng-isolate-scope"> <div> <div class="searchSection inline-block"></div> <div class="tagSearchSection inline-block margin-left"></div> </div> <div class="gridSection"> <table class="table table-hover"> <thead> <tr> <th>镜像名</th> <th>容器名</th> <th>建立时间</th> <th>运行时间</th> <th>状态</th> <th>IP</th> <th>暴露端口</th> <th class="text-right">操做</th> </tr> </thead> <tbody> <!-- ngRepeat: item in store --><!-- ngIf: !loadingState --> <tr text-editor-trigger-target="" data-ng-if="!loadingState" bindonce="" data-ng-repeat="item in containers" class="ng-scope"> <td><span ng-bind="item.Image"></span></td> <td><a ng-href="{{'http://' + item.Names[0] + '.test.com/'}}" target="_blank" ng-bind="item.Names"></a></td> <td><span>{{(item.Created * 1000) | date: 'yyyy-MM-dd HH:mm:ss'}}</span></td> <td><span ng-bind="item.Status"></span></td> <td><span ng-bind="item.State"></span></td> <td><span ng-bind="item.NetworkSettings.Networks.bridge.IPAddress"></span></td> <td><span ng-bind="item.Ports[0].PrivatePort"></span></td> <td class="text-right"> <div image-list-actions="" config="item" table-handler="item.tableHandler" class="ng-isolate-scope"> <a ng-show="item.State == 'running'" ng-click="stopContainer(item)">中止</a> <span class="text-explode">|</span> <a ng-click="restartContainer(item)">重启</a> </div> </td> </tr> <!-- end ngRepeat: item in store --> </tbody> </table> </div> </div> </div><!-- end ngIf: !vm.initial --> </div>
基本就是这个样子啦,不用登陆服务器,就能管理docker容器了,而后简单的在nginx成配置一个 basic auth ,使用用户名密码登录,成本很低,几乎没有什么内存消耗。是否是很轻量。socket