embark-docker/README.md

9.1 KiB

Embark for Docker

Quick start

In a Bash shell:

source <(curl -L https://bit.ly/run_embark)
run_embark demo
cd embark_demo
run_embark

Note that the run_embark demo command will create an embark_demo directory in the docker host's $PWD.

Usage via run.sh

run.sh is a Bash script that simplifies usage of the embark container: publishing ports, bind mounting a host volume, and so on.

When sourced, run.sh makes available a shell function named run_embark. When executed, run.sh forwards its arguments to the run_embark shell function.

Many aspects of run_embark's behavior can be overridden with environment variables, and that approach can be (optionally) combined with docker build.

export EMBARK_DOCKER_IMAGE=statusim/embark
export EMBARK_DOCKER_TAG=develop
export EMBARK_DOCKERFILE='https://github.com/embark-framework/embark-docker.git#master'
export EMBARK_VERSION='embark-framework/embark#develop'
export NODE_VERSION=10.7.0
export RUNNER='https://raw.githubusercontent.com/embark-framework/embark-docker/master/run.sh'

docker build \
       --build-arg EMBARK_VERSION=$EMBARK_VERSION \
       --build-arg NODE_VERSION=$NODE_VERSION \
       -t $EMBARK_DOCKER_IMAGE:$EMBARK_DOCKER_TAG \
       $EMBARK_DOCKERFILE

source <(curl $RUNNER)
run_embark demo
cd embark_demo
run_embark

Review the Dockerfile and run.sh for all possible overrides.

It's possible to pass additional options to docker run by specifying them before --.

run_embark [docker-run-opts] -- [command]

To completely replace the default docker run options:

EMBARK_DOCKER_RUN_OPTS_REPLACE=true
run_embark [docker-run-opts] -- [command]

By default run_embark invokes docker run with the --rm option, making the embark container ephemeral, i.e. it will not persist on the docker host's file system after the container exits. To override this behavior:

EMBARK_DOCKER_RUN_RM=false
run_embark [docker-run-opts] -- [command]

Note that if you have EMBARK_DOCKER_RUN_OPTS_REPLACE=true, then --rm would need to be provided in [docker-run-opts], i.e. EMBARK_DOCKER_RUN_RM will be effectively ignored.

Shortcuts

These are equivalent:

run_embark
run_embark run
run_embark embark run

The following are also equivalent:

run_embark demo
run_embark embark demo

The same is true for the rest of the embark commands. To see the full list:

run_embark --help

Utilities

The container comes equipped with nodeenv and nvm. A default Node.js environment is installed via nodeenv during image build and placed in ~embark/.local/nodeenv/default. The default environment is automatically activated by the container's entrypoint.

Both nodeenv and nvm can be used in interactive and non-interactive scripts.

nodeenv

These are equivalent:

nodeenv --prebuilt --node 10.7.0 ~/.local/nodeenv/my_node
simple_nodeenv 10.7.0 my_node

Activate and deactivate environments with nac and denac.

nac my_node
denac

Note that simple_nodeenv automatically activates an environment after installation, while nodeenv does not.

nvm

If nvm is preferable, it needs to be loaded first.

nvm_load
nvm install --latest-npm 8.11.3

nvm deactivate and nvm unload will work as expected. It's also possible to move between nodeenv and nvm environments without first deactivating or unloading.

nac default
nvm_load && nvm use v10.7.0
# ^ assuming 10.7.0 is already installed
nac default

micro

The micro editor is installed during image build, should you need to edit files within a running container.

install-extras.sh

Some nice-to-have utilities are not installed by default, but this can be done by running install-extras.sh as the root user in an already running container.

docker exec -it $container_id install-extras.sh

Commands

Simple

A single command with options can be supplied directly.

run_embark bash
run_embark node -i -e 'console.log(process.version)'
# ^ press return again to get a blank REPL prompt
run_embark ps -ef

Compound

Compound commands should be passed to bash -[i]c.

run_embark bash -c 'ps -ef && ls / ; which embark'
run_embark bash -c 'nvm_load && nvm install --latest-npm 8.11.3 && node --version && npm --version'

Bash here-documents can be used to compose scripts without employing an abundance of &&, ;, and \. Just be mindful of umatched quotes and quotes-escaping when building meta-scripts; in such scenarios, use of envsubst is probably called for.

run_embark bash -c 'exec bash << "SCRIPT"

simple_nodeenv 10.7.0 my_node
npm i -g http-server
exec http-server -p 8000

SCRIPT
'

Since run_embark mounts the docker host's $PWD into the container's /dapp, and since /dapp is the container's default working directory, it's also possible to do:

run_embark ./my_script.sh
# ^ assuming my_script.sh is in the docker host's $PWD

Just make sure the script has a #! line and that you did chmod +x my_script.sh on the docker host before invoking run_embark.

$EMBARK_DOCKER_RUN

For greater flexibility, you can specify a script with $EMBARK_DOCKER_RUN. Arguments passed to run_embark will be forwarded to the script, and extra flags can be provided to docker run to forward docker host environment variables.

Keep in mind that such scripts will run as the embark user owing to the container's entrypoint.

#!/bin/bash
# this script is located at /path/to/my_script.sh on the docker host, not necessarily in host's $PWD
# dangling "
c=container!
echo $HOST_HOSTNAME
echo $HOSTNAME
echo $@
echo $1
# a comment
echo $2
echo $3
eval echo \$$3
# another comment

Invoke with:

EMBARK_DOCKER_RUN=/path/to/my_script.sh
a=host!
run_embark -e HOST_HOSTNAME=$HOSTNAME -- $a b c

Node.js variant:

#!/usr/bin/env node
// this script is located at /path/to/my_node_script.js on the docker host, not necessarily in host's $PWD
const o = {c: 'container!'};
console.log(process.env.HOST_HOSTNAME);
console.log(process.env.HOSTNAME);
console.log(JSON.stringify(process.argv));
console.log(process.argv[2]);
console.log(process.argv[3]);
console.log(process.argv[4]);
console.log(o[process.argv[4]]);

Invoke the same way:

EMBARK_DOCKER_RUN=/path/to/my_node_script.js
a=host!
run_embark -e HOST_HOSTNAME=$HOSTNAME -- $a b c

docker exec

When executing compound commands via docer exec in a running embark container, su-exec and bash -[i]c can be used together.

docker exec -it $container_id su-exec embark \
       bash -ic 'exec bash << "SCRIPT"

simple_nodeenv 10.7.0 my_node || nac my_node
npm i -g http-server
exec http-server -p 8000

SCRIPT
'

To go non-interactive, manually source the embark user's .bash_env.

docker exec -it $container_id su-exec embark \
       bash -c 'exec bash << "SCRIPT"

. ~/.bash_env
simple_nodeenv 10.7.0 my_node || nac my_node
npm i -g http-server
exec http-server -p 8000

SCRIPT
'

Container development

Updating versions

  • Open Dockerfile
  • On the ARG directives, update necessary versions.

Building

Building requires Docker to be installed on your local machine.

Scripted

If you have Ruby installed in your system, run:

$ ruby script/build

To release, add --release as a parameter of the build script.

Manually

Building and releasing manually isn't too hard either, but there are a couple steps.

Tags

To facilitate the images being found, we tag them with the following rules (as an example, the 3.1.5 version will be used.)

  • Tag with statusim/embark:latest if 3.1.5 is the latest version.
  • Tag with statusim/embark:3.1.5
  • Tag with statusim/embark:3.1 if 3.1.5 is the highest patch level on 3.1
  • Tag with statusim/embark:3 if 3.1.5 is the highest minor and patch level on 3
Generating the image

To generate the image, run:

docker build . -t statusim/embark:<version> [...tags]

Releasing

Releasing requires that you're authenticated to Docker Hub. To do so, run:

$ docker login

Scripted

If you have Ruby installed in your system, run:

$ ruby script/build --release

Manual

Pushing the tags manually implies that the image has been previously built. To push your local images, run:

docker push statusim/embark:version