Skip to content

Instantly share code, notes, and snippets.

@kadamwhite
Last active February 10, 2021 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kadamwhite/01b15fc34c118d6c5e1f89ede3448af5 to your computer and use it in GitHub Desktop.
Save kadamwhite/01b15fc34c118d6c5e1f89ede3448af5 to your computer and use it in GitHub Desktop.
Node script to print out all running docker containers by IP
#!/usr/bin/env node
const child_process = require( 'child_process' );
/**
* Execute a command as a spawned process.
*
* @param {String} command A bash command string, excluding arguments.
* @param {String[]} args An array of argument strings for the provided command.
*/
const spawn = ( command, args ) => {
const output = [];
return new Promise( ( resolve, reject ) => {
const spawnedProcess = child_process.spawn( command, args );
spawnedProcess.stdout.on( 'data', ( message ) => {
output.push( message.toString() );
} );
spawnedProcess.on( 'error', err => reject( err ) );
spawnedProcess.on( 'close', ( code, signal ) => {
if ( code ) {
reject();
return;
}
resolve( output.join( '\n' ) );
} );
} );
};
/**
* Use child_process to run `docker ps` and `docker inspect` commands to return
* a JSON object with the ID, name, and IPs of all running containers.
*
* @async
* @returns {Object[]} Array of { name, id, ips } container objects.
*/
const getContainers = async () => {
try {
const psOutput = await spawn( 'docker', [
'ps',
'--format',
'{{.ID}},{{.Names}}',
] );
const containers = psOutput.trim().split( '\n' )
.map( ( line ) => {
const [ id, name ] = line.split( ',' );
return { id, name };
} );
for ( let container of containers ) {
// Hat-tip https://www.freecodecamp.org/news/how-to-get-a-docker-container-ip-address-explained-with-examples/
const ips = await spawn( 'docker', [
'inspect',
'--format',
'{{.NetworkSettings.IPAddress}},{{range .NetworkSettings.Networks}}{{.IPAddress}},{{end}}',
container.id,
] );
container.ips = ips.split( ',' )
.map( ( str ) => str.trim().replace( '<no value>', 'No IP' ) )
.filter( Boolean )
.sort();
}
return containers;
} catch ( e ) {
throw e;
}
};
const containersPromise = getContainers();
/**
* Given a URL, return the object defining the associated container.
*
* If no container is using an IP which appears in the URL, return null.
*
* @async
* @param {String} url A url e.g. http://172.18.0.8:8080
* @returns {Object|null} Container object { id, name, ips }, or else null.
*/
const getContainerByURL = async ( url ) => {
const containers = await containersPromise;
for ( let container of containers ) {
for ( let ip of container.ips ) {
if ( url.indexOf( ip ) > -1 ) {
return container;
}
}
}
return null;
}
/**
* Pretty-print the container namess by IP address.
*
* @async
* @returns {String} Nicely formatted table of containers by IP.
*/
const describeContainers = async () => {
const containers = await containersPromise;
const longestIPLength = containers.reduce( ( max, container ) => Math.max( max, container.ips.join( ', ' ).length ), 0 );
const longestNameLength = containers.reduce( ( max, container ) => Math.max( max, container.name.length ), 0 );
const pad = ( str, length ) => {
while ( str.length < length ) {
str = `${ str } `;
}
return str;
}
const sortedContainers = containers
.map( ( { ips, id, name } ) => `${
pad( `${ ips.join( ', ' ) }`, longestIPLength )
} ${
pad( name, longestNameLength )
} ${ id }` )
.sort();
return `\nDocker Containers by IP:\n\n${
`${ pad( 'IPs', longestIPLength ) } ${ pad( 'Name', longestNameLength ) } ID`
}\n${ sortedContainers.join( '\n' ) }`;
};
if ( require.main === module ) {
( async () => {
console.log( await describeContainers() );
} )();
}
module.exports = {
getContainers,
getContainerByURL,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment