Example DCli app in Docker

DCli is designed to work with docker and makes for an easy method of developing a Docker based app.

The following is an example Dockerfile showing how to ship a single DCli app in Docker

FROM google/dart as build

RUN mkdir /src
WORKDIR /src
RUN git clone https://github.com/noojee/batman.git

# remove the git clone and uncomment this lines for local dev.
# COPY batman /src/batman

WORKDIR /src/batman

RUN dart pub get
RUN dart compile exe /src/batman/bin/batman.dart -o /batman


# Build minimal  image from AOT-compiled `/batman`
FROM build
COPY --from=build /batman /batman
WORKDIR /
RUN /batman install

# Run a base line and schedule scans.
ENTRYPOINT ["/batman", "--quiet", "--no-colour", "cron", "--baseline", "30 22 * * * *"]

# remove the ENTRYPOINT and uncomment this line to enable interactive debugging.
# CMD ["bash"]

The above example use the batman project to show the steps required to run a DCli app in docker.

batman is a real app and a useful reference.

Of particular note batman includes its own cron daemon which allows it to schedule itself without requiring the Docker image to contain cron (which is rather difficult to do).

To build the docker image run:

docker build -t <imagename> .

To run the docker image:

docker run <imagename>

To debug the image, comment out the 'ENTRYPOINT' and uncomment 'CMD'

You can now connect to the docker image:

docker run -it <imagename> /bin/bash

Publish your docker image

The following DCli script is from the dcli_scripts project and automates pushing your app into docker hub.

You will need a docker hub account.

Place the script in your dart project tool directory (or alternatively activate dcli_scripts).

#! /bin/env dcli

// ignore_for_file: file_names
import 'dart:io';

import 'package:dcli/dcli.dart';

void main(List<String> args) {
  var parser = ArgParser()
    ..addOption('repo',
        abbr: 'r',
        mandatory: true,
        help: 'The name of the docker repository to publish to.');
  var project = DartProject.fromPath('.', search: true);
  var projectRootPath = project.pathToProjectRoot;
  print('projectRoot $projectRootPath');

  ArgResults parsed;
  try {
    parsed = parser.parse(args);
  } on FormatException catch (e) {
    printerr(red('Invalid CLI argument: ${e.message}'));
    exit(1);
  }

  var repo = parsed['repo'] as String;
  var projectName = project.pubSpec.name;
  var version = project.pubSpec.version;
  var name = '$repo/$projectName';

  var imageTag = '$name:$version';
  print('Pushing Docker image $imageTag.');

  print('docker path: ${findDockerFilePath()}');
  print(green('Building $projectName docker image'));
  'docker build -t$imageTag .'.start(workingDirectory: findDockerFilePath());
  print(green('Pushing docker image: $imageTag and latest'));
  var latestTag = '$name:latest';
  'docker image tag $imageTag $latestTag'.run;
  'docker push $imageTag'.run;
  'docker push $latestTag'.run;
}

String findDockerFilePath() {
  var current = pwd;
  while (current != rootPath) {
    if (exists(join(current, 'Dockerfile'))) {
      return current;
    }
    current = dirname(current);
  }
  return '.';
}

Last updated