docker_commander

pub package Null Safety

Docker image size Docker puuls Docker build

CI GitHub Tag New Commits Last Commits Pull Requests Code size

License

docker_commander is a Docker manager to easily automate a Docker Daemon, or a Docker Swarm:

  • Helpers to build a Docker network.
  • Helpers to manipulate files inside a running container.
  • Supports personalized containers.
  • Formulas: pre-defined code to install/uninstall containers.
  • Built-in pre-configured popular containers:

Running docker_commander image

A Docker image of docker_commander is provided at Docker HUB, allowing an easy and fast way to use docker_commander in any environment with Docker (even without Dart).

Pull the Docker image:

docker pull gmpassos/docker_commander

SERVER MODE (docker_commander_server):

Run the docker_commander image in SERVER mode, mapping port 8099 and Docker Host Daemon socket file (/var/run/docker.sock).

docker run --name docker_commander_server -d -t --rm -v /var/run/docker.sock:/var/run/docker.sock -p 8099:8099 gmpassos/docker_commander --server userx pass123

You need to provide an username and password (the parameters userxand pass123 above) to control the access to this docker_commander server. You will pass this credential, and the public mapped port (8099) to the DockerHostRemote, allowing it to connect to the server container. If you need to restrict address access, pass the parameter --private.

Follow the server output:

docker logs docker_commander_server -f

NOTE: To enable control of Docker Daemon from the docker_commander server container, you need to map the Docker Host Daemon socket file (/var/run/docker.sock). This won't require to run the container in a --privileged context or as root.

CONSOLE MODE (docker_commander_console):

Run the docker_commander image in CONSOLE mode, passing --console:

docker run -it --rm gmpassos/docker_commander --console userx your.server.host 8099

Console example:

<CONSOLE MODE>
ARGS: [--console, userx, your.server.host, 8099]

[docker_commander server: your.server.host:8099]
Please, provide the password for user 'userx':
password> pass123
------------------------------------------------------------------------------
DockerCommanderConsole{dockerCommander: DockerCommander{dockerHost: DockerHostRemote{serverHost: your.server.host, serverPort: 8099, secure: false, username: userx}, initialized: false. lastDaemonCheck: null}}
Initializing...
Initialization: true
------------------------------------------------------------------------------

$> ps
------------------------------------------------------------------------------
>> CONTAINER ID   IMAGE                       COMMAND                  CREATED             STATUS             PORTS                    NAMES
>> 0f229773e36f   gmpassos/docker_commander   "/usr/bin/dart run b…"   About an hour ago   Up About an hour   0.0.0.0:8099->8099/tcp   docker_commander_server
------------------------------------------------------------------------------
EXIT_CODE: 0

$> help
...

For more information:


Formulas

Formulas are a very easy way to install/uninstall and handle containers and services in docker_commander.

You can use docker_commander formulas from a repository. Below there's a simple example of how to use the standard repository (DockerCommanderFormulaRepositoryStandard) from a Dart code.

import 'package:docker_commander/docker_commander_vm.dart';

void main() async {
  // Creates a `DockerCommander` for a local host machine:
  var dockerCommander = DockerCommander(DockerHostLocal());
  
  // Initialize `DockerCommander`:
  await dockerCommander.initialize();
  
  // The formula repository to use:
  var repository = DockerCommanderFormulaRepositoryStandard();

  // Get the `apache` formula source:
  var formulaSource = await repository.getFormulaSource('apache');

  // Get the formula instance and perform setup:
  var formula = formulaSource!.toFormula() ;
  
  formula.setup(dockerCommander: dockerCommander);

  // Install the formula:
  var installed = await formula.install();

  //...

  // Stop the formula:
  var stopped = await formula.stop();

  //...
  
  // Start the formula:
  var start = await formula.start();

  //...
  
  // Uninstall the formula:
  var uninstalled = await formula.uninstall();
  
}

Defining a Formula

Formulas are pre-defined codes to handle install, uninstall, start, stop and other extra operations that a container, or group of containers, can have.

Formulas are defined using a high level languages, like Dart or Java. Any language supported by ApolloVM can be used.

Here's a simple example of an Apache formula source code in Dart:


class ApacheFormula {

  String getVersion() {
    return '1.0';
  }

  void install() {
    cmd('create-container apache httpd latest --port 80 --hostname apache');
    start();
  }

  void start() {
    cmd('start apache');
  }

  void stop() {
    cmd('stop apache');
  }

  void uninstall() {
    stop();
    cmd('remove-container apache --force');
  }

}

A formula source code will be parsed and executed by ApolloVM, allowing dynamic loading and execution, in a sandbox, of any formula by docker_commander.


Using a Formula through docker_commander_console:

To list the available formulas in the server:

$> list-formulas

------------------------------------------------------------------------------
FORMULAS:

  apache gitlab

------------------------------------------------------------------------------

To show information of a formula:

$> show-formula gitlab
------------------------------------------------------------------------------
FORMULA: gitlab

CLASS NAME: GitLabFormula

FIELDS:

  - imageGitlab: gitlab/gitlab-ce
  - imageGitlabRunner: gitlab/gitlab-runner
  - imageRunner: google/dart
  - network: gitlab-net
  - hostGitlabConfigPath: /srv/gitlab-runner/config

FUNCTIONS:

  - getVersion
  - pull
  - pullRunner
  - install
  - installRunner
  - registerRunner
  - start
  - stop
  - startRunner
  - stopRunner
  - uninstall
  - uninstallRunner

------------------------------------------------------------------------------

Using a formula.

## Pull images:
$> formula-exec gitlab pull
$> formula-exec gitlab pullRunner

## Install images (create containers and start):
$> formula-exec gitlab install

## Install optional GitLab Runner,
## personalizing field "hostGitlabConfigPath":
$> formula-exec gitlab installRunner --hostGitlabConfigPath /host/path/to/gitlab-config-dir/

## Register GitLab Runner,
## passing the host and token of GitLab,
## and the personalized field "hostGitlabConfigPath":
$> formula-exec gitlab registerRunner 172.30.0.2 zysByxVr9tss18BvLFxj --hostGitlabConfigPath /host/path/to/gitlab-config-dir/

## Starts the GitLab Runner, once it's registered.
$> formula-exec gitlab startRunner

NOTE: The function installRunner and registerRunner are personalizing the path of the GitLab config directory in the host machine using the field hostGitlabConfigPath.

Stopping and uninstalling a formula:

$> formula-exec gitlab stop

$> formula-exec gitlab uninstall

ApolloVM

ApolloVM is a simple and portable VM for Dart and Java, that can at runtime dynamically parse, execute and generate code in any platform (native, JS/Browser and Flutter).


Dart Usage

Local Docker

Here's a simple usage example for a local host machine:

import 'package:docker_commander/docker_commander_vm.dart';

void main() async {
  // Creates a `DockerCommander` for a local host machine:
  var dockerCommander = DockerCommander(DockerHostLocal());
  
  // Initialize `DockerCommander`:
  await dockerCommander.initialize();
  // Ensure that Docker daemon is running.
  await dockerCommander.checkDaemon();

  // Run Docker image `hello-world`:
  var dockerContainer = await dockerCommander.run('hello-world');

  // Waits the container to exit, and gets the exit code:
  var exitCode = await dockerContainer.waitExit();
  
  // Gets all the STDOUT as [String]. 
  var output = dockerContainer.stdout.asString;
  
  print(output);
  print('EXIT CODE: $exitCode');
}

Remote Docker

Here's another usage example for a remote host machine:

Server

Start DockerHostServer:

import 'package:docker_commander/docker_commander_vm.dart';

void main() async {
  
  // A simple username and password table:
  var authenticationTable = AuthenticationTable({'admin': '123'});

  // A `DockerHost` Server at port 8099:
  var hostServer = DockerHostServer(
          (user, pass) async => authenticationTable.checkPassword(user, pass),
      8099);

  // Starts the server and wait initialization:
  await hostServer.startAndWait();
  
}

Client

Client side using DockerHostRemote. Note that the code below can run in any platform, like JS (in a Web Browser) or any Flutter platform (Android, iOS, Web, Linux, macOS, Windows):

import 'package:docker_commander/docker_commander.dart';

void main() async {

  // Connect to a `DockerHost` running at '10.0.0.52:8099'
  var dockerHostRemote = DockerHostRemote('10.0.0.52', 8099, username: 'admin', password: '123');

  // Creates a `DockerCommander` for a remote host machine:
  var dockerCommander = DockerCommander(dockerHostRemote);
  
  // Initialize `DockerCommander` (at remote server):
  await dockerCommander.initialize();
  // Ensure that Docker daemon is running (at remote server):
  await dockerCommander.checkDaemon();

  // Run Docker image `hello-world` (at remote server):
  var dockerContainer = await dockerCommander.run('hello-world');

  // The behavior is the same of the example using `DockerHostLocal`.
  // The internal `DockerRunner` will sync remote output (stdout/sdterr) automatically!

  // ...
  
  // Gets all the STDOUT as [String]. 
  var output = dockerContainer.stdout.asString;
  print(output);
  
  // ...
  
}


PostgreSQLContainer

A pre-configured PostgreSQL Container:

import 'package:docker_commander/docker_commander_vm.dart';

void main() async {

  // Creates a `DockerCommander` for a local host machine:
  var dockerCommander = DockerCommander(DockerHostLocal());
  // Initialize `DockerCommander`:
  await dockerCommander.initialize();
  
  // Start PostgreSQL container:
  var dockerContainer = await PostgreSQLContainer().run(dockerCommander);

  // Print the current STDOUT of the container:
  var output = dockerContainer.stdout.asString;
  print(output);

  // Execute inside the container a `psql` command:
  var execPsql = await dockerContainer.exec('/usr/bin/psql',
      ['-d','postgres', '-U','postgres', '-c','\\l']);

  // Wait command to execute:
  var execPsqlExitCode = await execPsql.waitExit();

  // Command output:
  print( execPsql.stdout.asString );
  
  // Stops PostgreSQL, with a timeout of 20s:
  await dockerContainer.stop(timeout: Duration(seconds: 20));

  // Wait PostgreSQL to exit and get exit code:
  var exitCode = await dockerContainer.waitExit();

  // ...

}


ApacheHttpdContainer

A pre-configured container for the famous Apache HTTPD:

import 'package:docker_commander/docker_commander_vm.dart';
import 'package:mercury_client/mercury_client.dart';

void main() async {
    var dockerCommander = DockerCommander(DockerHostLocal());
    // Initialize `DockerCommander`:
    await dockerCommander.initialize();
    
    // The host port to map internal container port (httpd at port 80).
    var apachePort = 8081;
    
    var dockerContainer = await ApacheHttpdContainer()
        .run(dockerCommander, hostPorts: [apachePort]);
    
    // Get HTTPD configuration file:
    var httpdConf = await dockerContainer.execCat('/usr/local/apache2/conf/httpd.conf');

    // Get the host port of Apache HTTPD.
    var hostPort = dockerContainer.hostPorts[0];
    // Request a HTTP GET using hostPort:
    var response = await HttpClient('http://localhost:$hostPort/').get('index.html');
    
    // The body of the response
    var content = response.bodyAsString;
    print(content);
    
    // Stop Apache HTTPD:
    await dockerContainer.stop(timeout: Duration(seconds: 5));

}


NginxContainer

A pre-configured container for the famous NGINX proxy server.

This example shows a NGINX reverse proxy, that redirects HTTP requests at localhost:4082 to the internal Apache container, with hostname apache, at port 80.

import 'package:docker_commander/docker_commander_vm.dart';
import 'package:mercury_client/mercury_client.dart';

void main() async {
  var dockerCommander = DockerCommander(DockerHostLocal());
  // Initialize `DockerCommander`:
  await dockerCommander.initialize();

  // Docker Network for Apache HTTPD and NGINX containers:
  var network = await dockerCommander.createNetwork();

  // Start Apache HTTPD, mapping port 80 to 4081.
  var apacheContainer = await ApacheHttpdContainer().run(dockerCommander,
      hostPorts: [4081], network: network, hostname: 'apache');

  // Generate a NGINX configuration, mapping domain `localhost` to
  // docker host `apache` at port 80 (without HTTPS).
  var nginxConfig = NginxReverseProxyConfigurer(
      [NginxServerConfig('localhost', 'apache', 80, false)]).build();

  // Start a NGINX container using generated configuration.
  var nginxContainer = await NginxContainer(nginxConfig, hostPorts: [4082])
      .run(dockerCommander, network: network, hostname: 'nginx');

  // Request apache:80 (mapped in the host machine to localhost:4081)
  // trough NGINX reverse proxy at localhost:4082
  var response = await HttpClient('http://localhost:4082/').get('');

  // The Apache HTTPD response content:
  var apacheContent = response.bodyAsString;

  print(apacheContent);

  // Stop NGINX:
  await nginxContainer.stop(timeout: Duration(seconds: 5));

  // Apache Apache HTTPD:
  await apacheContainer.stop(timeout: Duration(seconds: 5));

  // Remove Docker network:
  await dockerCommander.removeNetwork(network);
}

See Also

See package docker_commander_test, for unit test framework with Docker containers.

Thanks to isoos@GitHub, author of the precursor package docker_process, that was substituted by this one.

Features and bugs

Please file feature requests and bugs at the issue tracker.

Author

Graciliano M. Passos: gmpassos@GitHub.

License

Apache License - Version 2.0

Libraries

docker_commander
docker_commander_vm