0
mirror of https://github.com/valentineus/simple-container.git synced 2025-04-28 00:41:24 +03:00

The first working beta version

This commit is contained in:
Valentin Popov 2017-10-06 23:51:11 +04:00
parent 2c2d12f5f6
commit b431dbe252
3 changed files with 203 additions and 63 deletions

View File

@ -7,26 +7,32 @@
Simple and fast work with the Docker container. Simple and fast work with the Docker container.
It uses the library
[dockerode](https://github.com/apocas/dockerode).
## Installation ## Installation
```bash ```bash
npm install --save simple-container npm install --save simple-container
``` ```
## Using ## Using
A simple example: A simple example that creates and starts a container:
```JavaScript ```JavaScript
import Container from 'simple-container'; import Containers from 'simple-container';
var container = new Container(); var containers = new Containers();
/* Create the container */ containers.create('postgres:alpine').then(container => {
container.create('hello-world:latest'); console.info(`The ${container.id} container was created.`);
start(container);
});
/* Start the container */ /* Run the created container */
container.start(); function start(container) {
container.start().then(() => {
/* Stop and destroy the container */ console.info(`The ${container.id} container is running.`);
container.destroy(); });
}
``` ```
### Remote connection ### Remote connection
@ -34,7 +40,7 @@ By default, the local service is used.
For example, if you want to use connection settings: For example, if you want to use connection settings:
```JavaScript ```JavaScript
var container = new Container({ var containers = new Containers({
host: '127.0.0.1', host: '127.0.0.1',
port: 3000 port: 3000
}); });
@ -48,12 +54,12 @@ You can create a container in two ways.
A simple way - to specify the name of the image: A simple way - to specify the name of the image:
```JavaScript ```JavaScript
container.create('hello-world:latest'); containers.create('hello-world:latest');
``` ```
Another way - to provide an object with parameters: Another way - to provide an object with parameters:
```JavaScript ```JavaScript
container.create({ containers.create({
Image: 'postgres:alpine', Image: 'postgres:alpine',
Env: ['POSTGRES_PASSWORD = password'], Env: ['POSTGRES_PASSWORD = password'],
Ports: [{ Ports: [{
@ -77,7 +83,7 @@ var auth = {
serveraddress: 'https://index.docker.io/v1' serveraddress: 'https://index.docker.io/v1'
}; };
container.create({ containers.create({
Image: 'project:latest', Image: 'project:latest',
authconfig: auth authconfig: auth
}); });
@ -87,11 +93,11 @@ Details in
[the documentation](https://github.com/apocas/dockerode#pull-from-private-repos). [the documentation](https://github.com/apocas/dockerode#pull-from-private-repos).
## Debugging ## Debugging
Use the `DEBUG` variable with the `container` option. Use the `DEBUG` variable with the `containers` option.
Result of output: Result of output:
```bash ```bash
$ DEBUG="container" node ./example.js $ DEBUG="containers" node ./example.js
container { status: 'Pulling from library/postgres', id: 'alpine' } +0ms container { status: 'Pulling from library/postgres', id: 'alpine' } +0ms
container { status: 'Already exists', container { status: 'Already exists',
container progressDetail: {}, container progressDetail: {},
@ -104,7 +110,7 @@ $ DEBUG="container" node ./example.js
Or redefine the function to your own: Or redefine the function to your own:
```JavaScript ```JavaScript
container.debug = function() { containers.debug = function() {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
/* Debugger code */ /* Debugger code */
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "simple-container", "name": "simple-container",
"version": "0.0.0-alpha.1", "version": "0.0.0-beta.1",
"description": "Simple and fast work with the Docker container", "description": "Simple and fast work with the Docker container",
"homepage": "https://github.com/valentineus/simple-container", "homepage": "https://github.com/valentineus/simple-container",
"license": "MIT", "license": "MIT",
@ -26,7 +26,6 @@
"mocha": "^4.0.0" "mocha": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"ancient-funicular": "^3.0.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"dockerode": "^2.5.1" "dockerode": "^2.5.1"
}, },

View File

@ -1,4 +1,3 @@
import { Item } from 'ancient-funicular';
import createDebug from 'debug'; import createDebug from 'debug';
import Docker from 'dockerode'; import Docker from 'dockerode';
import { statSync } from 'fs'; import { statSync } from 'fs';
@ -6,14 +5,12 @@ import { statSync } from 'fs';
/** /**
* @class Container * @class Container
*/ */
export default class Container extends Item { export default class Containers {
/** /**
* @constructs Container * @constructs Container
* @param {Object=} [options] - Service connection settings * @param {Object=} [options] - Service connection settings
*/ */
constructor(options) { constructor(options) {
super();
/** /**
* @protected * @protected
* @type {Object} * @type {Object}
@ -26,11 +23,11 @@ export default class Container extends Item {
this._docker = new Docker(options); this._docker = new Docker(options);
} }
else { else {
var socket = process.env.DOCKER_SOCKET || '/var/run/docker.sock'; var socket = this._getSocket();
var stats = statSync(socket); var stats = statSync(socket);
if (!stats.isSocket()) { if (!stats.isSocket()) {
throw new Error('Local service is not found.'); throw new Error('');
} }
this._docker = new Docker({ this._docker = new Docker({
@ -41,14 +38,15 @@ export default class Container extends Item {
/** /**
* @protected * @protected
* @param {Object|String} options - Container parameters * @param {String|Object} options - The name of the image or options
* @description Creates and registers a container in the system. * @returns {Promise} Returns the container object
* @description Creates a container by options or name, returning the management interface.
*/ */
create(options) { create(options) {
var self = this; var self = this;
if (!self._isString(options) && !self._isObject(options)) { if (!self._isString(options) && !self._isObject(options)) {
throw new Error('The variable \'options\' is not correct.'); throw new Error('');
} }
if (self._isString(options)) { if (self._isString(options)) {
@ -56,42 +54,190 @@ export default class Container extends Item {
options = { Image }; options = { Image };
} }
self._pullImage(options.Image, (error) => { return new Promise((resolve, reject) => {
self._handlerError(error); self._getImage(options.Image, (error) => {
self._createContainer(options); if (error) {
reject(error);
}
self._createContainer(options, (error, container) => {
if (error) {
reject(error);
}
resolve(container);
});
});
}); });
} }
/** /**
* @protected * @protected
* @description Stops and destroys the container. * @param {String=} [id] - Container ID
* @returns {Promise} Returns the container or container object
* @description Returns the container management interface.
*/ */
destroy() {} get(id) {
/**
* @protected
* @param {String} image - Name of the image
* @param {Function} callback - Called function
* @description Pulls out the image of the container.
*/
_pullImage(image, callback) {
var self = this; var self = this;
self._docker.pull(image).then(stream => {
self._docker.modem.followProgress(stream, callback, self.debug); if (id && !self._isString(id)) {
}).catch(error => self._handlerError(error)); throw new Error('');
}
return new Promise((resolve, reject) => {
self._getContainers((error, list) => {
if (error) {
reject(error);
}
if (self._isString(id)) {
self._findContainer(list, id, (result) => {
resolve(self._getContainer(result.Id));
});
}
else {
self._createListContainers(list, (result) => {
resolve(result);
});
}
});
});
} }
/** /**
* @protected * @protected
* @param {Object} options - Container settings * @param {String=} [id] - Container ID
* @description Creating a container and registering management. * @returns {Promise} Returns the container or container object
* @description Searches in existing containers.
*/ */
_createContainer(options) { info(id) {
var self = this; var self = this;
self._docker.createContainer(options).then(container => {
/* @todo Class registration */ if (id && !self._isString(id)) {
self.debug(container); throw new Error('');
}).catch(error => self._handlerError(error)); }
return new Promise((resolve, reject) => {
self._getContainers((error, list) => {
if (error) {
reject(error);
}
if (self._isString(id)) {
self._findContainer(list, id, (result) => {
resolve(result);
});
}
else {
self._createInformationList(list, (result) => {
resolve(result);
});
}
});
});
}
/**
* @protected
* @param {Object} options - Settings created by the container
* @param {Function} callback - Callback after creation
* @description Creates a container and returns its interface.
*/
_createContainer(options, callback) {
this._docker.createContainer(options, (error, container) => {
callback(error, container);
});
}
/**
* @protected
* @param {Array} list - List of containers
* @param {Function} callback - Callback after building the list
* @description Creates a list of containers for the user.
*/
_createInformationList(list, callback) {
callback(list.reduce((result, item) => {
result[item.Id] = item;
return result;
}, {}));
}
/**
* @protected
* @param {Array} list - List of containers
* @param {Function} callback - Callback after building the list
* @description Creates a list of container interfaces.
*/
_createListContainers(list, callback) {
var self = this;
callback(list.reduce((result, item) => {
result[item.Id] = self._getContainer(item.Id);
return result;
}, {}));
}
/**
* @protected
* @returns {String} Socket
* @description Getting the system socket.
*/
_getSocket() {
return process.env.DOCKER_SOCKET || '/var/run/docker.sock';
}
/**
* @protected
* @param {Function} callback - Callback after receiving the list
* @description Getting a list of all available containers in the system.
*/
_getContainers(callback) {
this._docker.listContainers({ all: true }, (error, list) => {
callback(error, list);
});
}
/**
* @protected
* @param {String} id - Container ID
* @returns {Object} Container interface
* @description Getting the interface of the container.
*/
_getContainer(id) {
return this._docker.getContainer(id);
}
/**
* @protected
* @param {String} image - The name of the image
* @param {Function} callback - Callback after download
* @description Load the image needed for the container.
*/
_getImage(image, callback) {
var self = this;
self._docker.pull(image, (error, stream) => {
if (error) {
callback(error);
}
self._docker.modem.followProgress(stream, callback, self.debug);
});
}
/**
* @protected
* @param {Array} list - List of containers
* @param {String} id - Container ID
* @param {Function} callback - Callback with the search result
* @description Search for a specific container from the general list of containers.
*/
_findContainer(list, id, callback) {
list.find(item => {
if (item.Id == id) {
callback(item);
}
});
} }
/** /**
@ -114,24 +260,13 @@ export default class Container extends Item {
return typeof value === 'object'; return typeof value === 'object';
} }
/**
* @protected
* @param {*} error - A string with an error
* @description Handles the error if present.
*/
_handlerError(error) {
if (error) {
throw new Error(error);
}
}
/** /**
* @param {*} Any variables * @param {*} Any variables
* @description A simple debugger. * @description A simple debugger.
*/ */
debug() { debug() {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var debug = createDebug('container'); var debug = createDebug('containers');
debug.apply(null, args); debug.apply(null, args);
} }
} }