Docker.Container.js

JavaScript source for A Docker module for Node.js, 160 lines. Raw file

const Security = require('Security');

const Docker =
{
    Daemon: require('./Docker.Daemon'),

    Container:
    {
        Command: (containerName, command) => {
            containerName = Security.String(containerName)
            command = Security.String(command)

            // const containerId = Docker.Container.ID(containerName)
            const commandArray = ['exec', containerName, command]

            return Docker.Daemon.Execute(commandArray)
        },
        /**
         * Gets the ID of the container based on the container name
         *
         * @param string containerName
         * @returns int
         * @throws Error if the container is not found or there are multiple with the same name
         */
        ID: ( containerName ) =>
        {
            containerName = Security.String(containerName)
            const command = [`container`, `ls`, `-a`, `-q`, `-f`, `name=${containerName}`];

            return Docker.Daemon.Execute(command, (input) => {

                if (input.trim() === '') {
                    throw new Error("Container not found: '" + containerName + "'")
                }

                const lines = input.trim().split('\n')
                const regExp = /^[a-f0-9A-F]+$/;
                const linesAreHashes = lines.map(line => regExp.test(line.trim()))
                const allLinesAreHashes = linesAreHashes.reduce((a, b) => a && b)

                if (allLinesAreHashes) {
                    if (lines.length === 1) {
                        return lines[0].trim()
                    } else {
                        throw new Error("Multiple containers with the same name: '" + containerName + "'")
                    }
                } else {
                    throw new Error("Unexpected output from docker container ls: '" + input + "'")
                }
            })
        },

        /**
         * Starts a container
         *
         * @param imageName string
         * @param containerName string
         * @param extraArguments string
         * @returns string
         * @throws Error if the container could not be started
         */
        Start: (imageName, containerName, extraArguments) =>
        {
            imageName = Security.String(imageName)
            containerName = Security.String(containerName)
            extraArguments = Security.Array(Security.String)(extraArguments)

            const command = [`run`, `-itd`, ...extraArguments, `--name ${containerName}`, `${imageName}:latest`];

            const containerId = Docker.Daemon.Execute( command, (input) => {
                const [hashToCompare] = Docker.Daemon.SplitOutput( input )
                const regExp = /\b([a-f0-9]{64})\b/

                if (!regExp.test(hashToCompare.trim())) {
                    throw new Error("Invalid hash format: '"+input+"'")
                }

                return hashToCompare;
            })

            if (!containerId) {
                throw new Error("Unable to start container")
            }

            return containerId;
        },

        Stop: (containerName) =>
        {
            containerName = Security.String(containerName)

            if( Docker.Container.Exists( containerName ) ) {
                const containerId = Docker.Container.ID( containerName )

                const command = [`stop`, containerId];

                const parsingCb = (input) => input.toLowerCase().trim() === containerId;
                const hasStopped = Docker.Daemon.Execute( command, parsingCb )

                if (!hasStopped) {
                    throw new Error("Unable to delete container")
                }
            }

        },

        Remove: (containerName) =>
        {
            containerName = Security.String(containerName)
            if( Docker.Container.Exists(containerName) ) {
                const containerId = Docker.Container.ID( containerName )
                const command = [`rm`, containerId];

                const parsingCb = (input) => {
                    if (input.toLowerCase().trim() !== containerId) {
                        throw new Error("Unable to delete container")
                    }
                };

                Docker.Daemon.Execute( command, parsingCb )
            }
        },

        Exists: (containerName, isRunning=false) =>
        {
            containerName = Security.String(containerName)

            const command = isRunning
                ? [`container`, `ls`, `-q`, `-f`, `name=${containerName}`]
                : [`container`, `ls`, `-a`, `-q`, `-f`, `name=${containerName}`];
            return Docker.Daemon.Execute(command, (input) => {

                if( input.trim() === '' ) {
                    return false;
                }

                const lines = input.trim().split('\n')
                const regExp = /^[a-f0-9A-F]+$/;
                const linesAreHashes = lines.map( line => regExp.test(line.trim()) )
                const allLinesAreHashes = linesAreHashes.reduce( (a,b) => a && b )

                if( allLinesAreHashes ) {
                    return true;
                }
                else {
                    throw new Error("Unexpected output from docker images: '" + input + "'")
                }
            })
        },

        Logs: (containerName) => {
            containerName = Security.String(containerName)

            const command = [`logs`, '-f', containerName];
            return Docker.Daemon.Execute(command)
        }
    }
}

module.exports = Docker.Container