先說說原理,其實很簡單,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