<commit_before>= Arquillian Cube

Documentation for version Alpha6 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha6/README.adoc

Documentation for version Alpha5 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha5/README.adoc

Documentation for version Alpha4 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha4/README.adoc


WARNING: 1.0.0.Alpha7 breaks incompatibility with previous versions in some cases. The major difference is that instead of using the _boot2docker_ keyword to refer to the auto resolved boot2docker ip in the _serverUri_ parameter, you should now used _dockerHost_.

== What is this?

*Arquillian Cube* is an _Arquillian_ extension that can be used to manager _Docker_ containers from _Arquillian_.

Extension is named *Cube* for two reasons:

* Because Docker is like a cube
* Because http://en.memory-alpha.org/wiki/Borg_cube[Borg starship] is named *cube* and well because we are moving tests close to production we can say that "any resistance is futile, bugs will be assimilated".

With this extension you can start a _Docker_ container with a server installed, deploy the required deployable file within it and execute _Arquillian_ tests.

The key point here is that if _Docker_ is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before.

But it also lets you start a container with every required service like database, mail server, ... and instead of stubbing or using fake objects your tests can use real servers.

[WARNING]
====
This extension has been developed and tested on a Linux machine with the _Docker_ server already installed.
It works with *Boot2Docker* as well in _Windows_ and _MacOS_ machines, but some parameters like _host ip_ must be the _Boot2Docker_ server instead of _localhost_ (in case you have _Docker_ server installed inside your own machine).

One of the best resources to learn about why using _Boot2Docker_ is different from using _Docker_ in Linux can be read here http://viget.com/extend/how-to-use-docker-on-os-x-the-missing-guide
====

== Preliminaries

*Arquillian Cube* relies on https://github.com/docker-java/docker-java[docker-java] API.

To use *Arquillian Cube* you need a _Docker_ daemon running on a computer (it can be local or not), but probably it will be at local.

By default the _Docker_ server uses UNIX sockets for communicating with the _Docker_ client. *Arquillian Cube* will attempt to detect the operating system it is running on and either set _docker-java_ to use UNIX socket on _Linux_ or to <<Boot2Docker>> on _Windows_/_Mac_ as the default URI.

If you want to use TCP/IP to connect to the Docker server, you'll need to make sure that your _Docker_ server is listening on TCP port.
To allow _Docker_ server to use TCP add the following line to +/etc/default/docker+:

+DOCKER_OPTS="-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"+

After restarting the _Docker_ daemon you need to make sure that _Docker_ is up and listening on TCP.

[source, terminal]
----
$ docker -H tcp://127.0.0.1:2375 version

Client version: 0.8.0
Go version (client): go1.2
Git commit (client): cc3a8c8
Server version: 1.2.0
Git commit (server): fa7b24f
Go version (server): go1.3.1
----

If you cannot see the client and server versions then it means that something is wrong with the _Docker_ installation.

== Basic Example

After having a _Docker_ server installed we can start using *Arquillian Cube*.
In this case we are going to use a very simple example using a _Docker_ image with _Apache Tomcat_ and we are going to test a _Servlet_ on it.

[source, java]
.HelloWorldServlet.java
----
@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("Hello World");
  }
}
----

[source, java]
.HelloWorldServletTest.java
----
@RunWith(Arquillian.class)
public class HelloWorldServletTest {

  @Deployment(testable=false) //<1>
  public static WebArchive create() {
    return ShrinkWrap.create(WebArchive.class, "hello.war").addClass(HelloWorldServlet.class); //<2>
  }

  @Test
  public void should_parse_and_load_configuration_file(@ArquillianResource URL resource) throws IOException { //<3>

    URL obj = new URL(resource, "HelloWorld");
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");

    BufferedReader in = new BufferedReader(
            new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    assertThat(response.toString(), is("Hello World"));//<4>
  }
}
----
<1> In this case we are running the test as a client. So in fact this test is executed against the container instead of inside the container.
<2> No changes in this part, we need to create a deployable file, and because we are testing against _Tomcat_, a _war_ file is created.
<3> Because the test is run as client, we can use +@ArquillianResource+ to get the URL where the file is deployed. Note that this will be the URL to access _Tomcat_ running inside the _Docker_ container.
<4> Typical jUnit assertion of servlet response.

Now this test could be run in any container, there is nothing that ties this to _Docker_.
Next step is adding some dependencies apart from the typical _Arquillian_ dependencies.

[source, xml]
.pom.xml
----
<dependency>
  <groupId>org.arquillian.cube</groupId>
  <artifactId>arquillian-cube-docker</artifactId> <!--1-->
  <version>${project.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.jboss.arquillian.container</groupId>
  <artifactId>arquillian-tomcat-remote-7</artifactId> <!--2-->
  <version>1.0.0.CR7</version>
  <scope>test</scope>
</dependency>
----
<1> Adds *Arquillian Cube* dependency.
<2> From the point of view of _Arquillian_, _Tomcat_ is being executed in a remote host (in fact this is true because _Tomcat_ is running inside _Docker_ which is external to _Arquillian_), so we need to add the remote adapter.

And finally we need to configure _Tomcat_ remote adapter and *Arquillian Cube* in +arquillian.xml+ file.

[source, xml]
.arquillian.xml
----
<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://jboss.org/schema/arquillian"
  xsi:schemaLocation="http://jboss.org/schema/arquillian
  http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

  <extension qualifier="docker"> <!--1-->
      <property name="serverVersion">1.12</property> <!--2-->
      <property name="serverUri">http://localhost:2375</property> <!--3-->
      <property name="dockerContainers"> <!--4-->
          tomcat:
            image: tutum/tomcat:7.0
            exposedPorts: [8089/tcp]
            await:
              strategy: polling
            env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
            portBindings: [8089/tcp, 8080/tcp]
      </property>
  </extension>

  <container qualifier="tomcat" default="true"> <!--5-->
      <configuration>
          <property name="host">localhost</property> <!--6-->
          <property name="httpPort">8080</property> <!--7-->
          <property name="user">admin</property> <!--8-->
          <property name="pass"><PASSWORD></property>
      </configuration>
  </container>

</arquillian>
----
<1> *Arquillian Cube* extension is registered.
<2> _Docker_ server version is required.
<3> _Docker_ server URI is required. In case you are using a remote _Docker_ host or _Boot2Docker_ here you need to set the remote host ip, but in this case _Docker_ server is on same machine.
<4> A _Docker_ container contains a lot of parameters that can be configured. To avoid having to create one XML property for each one, a YAML content can be embedded directly as property.
<5> Configuration of _Tomcat_ remote adapter. Cube will start the _Docker_ container when it is ran in the same context as an _Arquillian_ container with the same name.
<6> Host can be _localhost_ because there is a port forwarding between container and _Docker_ server.
<7> Port is exposed as well.
<8> User and password are required to deploy the war file to remote _Tomcat_.

And that's all.
Now you can run your test and you will see how _tutum/tomcat:7.0_ image is downloaded and started.
Ports 8080 (Tomcat standard port) and 8089(JMX port used by Arquillian) are exposed.
Finally in _env_ section, environment variables are set. Read next link to understand why this is required https://docs.jboss.org/author/display/ARQ/Tomcat+7.0+-+Remote

== Configuration

*Arquillian Cube* requires some parameters to be configured, some related with _Docker_ server and others related on the image that is being used.
Let's see valid attributes:

[cols="2*"]
|===
|serverVersion
|Version of REST API provided by_Docker_ server. You should check on the _Docker_ site which version of REST API is shipped inside installed _Docker_ service. This field is not mandatory and if it's not set the default provided version from _docker-java_ will be used.

|serverUri
|Uri of _Docker_ server. If the _Docker_ server is running natively on Linux then this will be an URI pointing to _localhost_ docker host but if you are using _Boot2Docker_ or a remote _Docker_ server then the URI should be changed to point to the _Docker_ remote _URI_. It can be a unix socket URI as well in case you are running _Docker_ on Linux (+unix:///var/run/docker.sock+). Also you can read at <<automatic-resolution, this section>> about automatic resolution of serverUri parameter. Also you can use `DOCKER_HOST` java property or system environment to set this parameter.

|dockerRegistry
|Sets the location of Docker registry. Default value is the official _Docker_ registry located at https://registry.hub.docker.com

|username
|Sets the username to connect to Docker registry.

|password
|Sets the password to connect to Docker registry.

|dockerContainers
|Each _Docker_ image (or container) can be configured with different parameters. This configuration is provided in YAML format. This property can be used to embed as YAML string value, all configuration.

|dockerContainersFile
|Instead of embedding YAML as a string, you can set the location of a YAML file with this attribute. The location can be a relative from the root of the project or also a URI that is converted to URL so you can effectively have docker definitions on remote sites.

|definitionFormat
|Sets the format of content expressed in `dockerContainers` attribute or in file set in `dockerContainersFile`. It can contain two possible values _CUBE_ (default one in case of not set) to indicate that content is written following <<cube-format, Arquillian Cube>> format or _COMPOSE_ to indicate that content is written following <<docker-compose-format, Docker Compose>> format.

|autoStartContainers
|Cube will normally start a _Docker_ container when it has the same name as an active _Arquillian_ container and all the containers defined as links to this container, so basically _Cube_ resolves all the container depdendencies as well e.g. a database where the application saves data, or mail server where application sends an email. That works for things that are _DeployableContainer_'s. For any other container services that might not have a link to the _DeployableContainer_, e.g. a monitor, you can use the _autoStartContainers_ option to define which _Docker_ containers to automatically start up. The option takes a comma separated list of _Docker_ container ids. e.g. _monitor_. *Arquillian Cube* will attempt to start the containers in parallel if possible as well as start any linked containers. Also if you need to start several images, instead of adding them as CSV, you can use a regular expression by prefixing with `regexp:`, for example setting the property to `regexp:a(.*)` would start all container ids starting with _a_. 

|certPath
|Path where certificates are stored. If you are not using _https_ protocol this parameter is not required. This parameter accepts starting with ~ as home directory

|boot2dockerPath
|Sets the full location (and program name) of _boot2docker_. For example +/opt/boot2dockerhome/boot2docker+.

|dockerMachinePath
|Sets the full location (and program name) of _docker-machine_. For example +/opt/dockermachinehome/docker-machine+.

|machineName
|Sets the machine name in case you are using docker-machine to manage your docker host. This parameter is mandatory when using docker-machine.

|connectionMode
|Connection Mode to bypass the Create/Start Cube commands if the a Docker Container with the same name is already running on the target system. This parameter can receive three possible values. _STARTANDSTOP_ which is the default one if not set any and simply creates and stops all Docker Containers. If a container is already running, an exception is thrown. _STARTORCONNECT_ mode tries to bypass the Create/Start Cube commands if a container with the same name is already running, and if it is the case doesn’t stop it at the end. But if container is not already running, Cube will start one and stop it at the end of the execution. And last mode is _STARTORCONNECTANDLEAVE_ which is exactly the same of _STARTORCONNECT_ but if container is started by Cube it won’t be stopped at the end of the execution so it can be reused in next executions.
|===

Some of these properties can be provided by using standard Docker system environment variables so you can set once and use them in your tests too.
Moreover you can set as Java system properties (-D...) as well.

[cols="2*"]
|===
|serverUri
|DOCKER_HOST

|certPath
|DOCKER_CERT_PATH

|machineName
|DOCKER_MACHINE_NAME
|===

In the next example you can see a whole YAML document with configuration properties.
Keep in mind that almost all of them are configuration parameters provided by _Docker_ remote API.
In this example we are going to explain the attributes that are most used and special cases.
Of course not all of them are mandatory:

NOTE: In YAML adding brackets ("[" "]") is for setting a list.

[[cube-format]]
[source, yaml]
----
tomcat: #1
  image: tutum/tomcat:7.0 #2
  exposedPorts: [8089/tcp] #3
  await: #4
    strategy: polling #5
  workingDir: .
  alwaysPull: false
  disableNetwork: true
  hostName: host
  portSpecs: [80,81]
  user: alex
  tty: true
  stdinOpen: true
  stdinOnce: true
  memoryLimit: 1
  memorySwap: 1
  cpuShares: 1
  cpuSet: a
  extraHosts: a
  attachStdin: true
  attachStderr: true
  env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089] #6
  cmd: [] #7
  dns: [127.0.0.1]
  volumes: [/tmp]
  volumesFrom: [tomcat]
  binds:
    - /host:/container:ro
  links:
    - name:alias
    - name2:alias2
  portBindings: [8089/tcp, 8081->8080/tcp] #8
  privileged: true
  publishAllPorts: true
  networkMode: host
  dnsSearch: [127.0.0.1]
  entryPoint: [sh]
  devices:
    cGroupPermissions: a
    pathOnHost: b
    pathInContainer: c
  restartPolicy: #10
    name: failure
    maximumRetryCount: 1
  capAdd: [a]
  capDrop: [b]
  extends: container-id #9
----
<1> The name that are going to be assign to running container. It is *mandatory*.
<2> The name of the image to be used. It is *mandatory*. If the image has not already been pulled by the _Docker_ server, *Arquillian Cube* will pull it for you. If you want to always pull latest image before container is created, you can configure *alwaysPull: true*.
<3> Sets exposed ports of the running container. It should follow the format _port number_ slash(/) and _protocol (udp or tcp). Note that it is a list and it is not mandatory.
<4> After a container is started, it starts booting up the defined services/commands. Depending on the nature of service, the lifecycle of these services are linked to start up or not. For example Tomcat, Wildlfy, TomEE and in general all Java servers must be started in foreground and this means that from the point of view of the client, the container never finishes to start. But on the other side other services like Redis are started in background and when the container is started you can be sure that Redis server is there. To avoid executing tests before the services are ready, you can set which await strategy should be used from *Arquillian Cube* side to accept that _Docker_ container and all its defined services are up and ready. It is not mandatory and by default polling with _ss_ command strategy is used.
<5> In +strategy+ you set which strategy you want to follow. Currently three strategies are supported. _static_, _native_ and _polling_.
<6> You can pass environment variables by using `env`. In this section you can set special `dockerServerIp` string which at runtime will be replaced by _Cube_ to current docker server ip.
<7> After the container is up, a list of commands can be executed within it.
<8> Port forwarding is configured using `portBinding` section. It contains a list of `exposedPort` and `port` separated by arrow (_->_). If only one port is provided, *Arquillian Cube* will expose the same port number. In this example the exposed port 8089 is mapped to 8089 and exposed port 8080 is mapped to 8081.
<9> You can extend another configuration. Any top level element and it's children from the target container-id will be copied over to this configuration, unless they have been defined here already.

As we've seen in the basic example the definition of the Arquillian Cube scenarios are described in `dockerContainers` property.
But if you want you can avoid using this property by simply creating a file called `cube` in the root of the classpath of your project.
_Arquillian Cube_ will read it as if it was defined in `arquilllian.xml` file.

[source, yaml]
.src/test/resources/cube
----
tomcat:
  image: tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: polling
  env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
  portBindings: [8089/tcp, 8080/tcp]
----

=== Await

After a container is started, it starts booting up the defined services/commands.
Depending on the nature of service, the lifecycle of these services are linked to start up or not.
For example Tomcat, Wildlfy, TomEE and in general all Java servers must be started in foreground and this means that from the point of view of the _Docker_ client, the container never finishes to start.
But on the other side other services like Redis are started in background and when the container is started you can be sure that Redis server is there.
To avoid executing tests before the services are ready, you can set which await strategy should be used from *Arquillian Cube* side to accept that _Docker_ container and all its defined services are up and ready.

Currently next await strategies are supported:

native:: it uses *wait* command. In this case current thread is waiting until the _Docker_ server notifies that has started. In case of foreground services this is not the approach to be used.
polling:: in this case a polling (with _ping_ or _ss_ command) is executed for 5 seconds against all exposed ports. When communication to all exposed ports is acknowledged, the container is considered to be up. This approach is the one to be used in case of services started in foreground. By default _polling_ executes _ss_ command inside the running container to know if the server is already running. You can use a _ping_ from client by setting +type+ attribute to +ping+; Note that _ping_ only works if you are running _Docker_ daemon on +localhost+. In almost all cases the default behaviour matches all scenarios. If it is not specified, this is the default strategy.
static:: similar to _polling_ but it uses the host ip and specified list of ports provided as configuration parameter. This can be used in case of using _Boot2Docker_.
sleeping:: sleeps current thread for the specified amount of time. You can specify the time in seconds or milliseconds.

By default in case you don't specify any _await_ strategy, polling with _ss_ command is used.

[source, yaml]
.Example native
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: native
----

[source, yaml]
.Example polling using ss command by default
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: polling
    sleepPollingTime: 200 s #1
    iterations: 3 #2
----
<1> Optional parameter to configure sleeping time between poling. You can set in seconds using _s_ or miliseconds using _ms_. By default time unit is miliseconds and value 500.
<2> Optional parameter to configure number of retries to be done. By default 10 iterations are done.

[source, yaml]
.Example static
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: static
    ip: localhost
    ports: [8080, 8089]
----

[source, yaml]
.Example sleeping
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: sleeping
    sleepTime: 200 s #1
----
<1> Optional parameter to configure sleeping time between poling. You can set in seconds using _s_ or miliseconds using _ms_. By default time unit is miliseconds and value 500.

=== Inferring exposedPorts from portBinding

When you are using _Docker_ you can set two different parameters, +exposedPort+ and +portBinding+.
+exposedPorts+ are ports that are available inside _Docker_ infrastructure and they are used for communication between _Docker_ containers but not from outside.
On the other side +portBindings+ are a way to instruct _Docker_ container to publish a port to be available from outside (for example from our test).

It seems reasonable that if you set a port binding this port should automatically be exposed port as well.
For this reason in *Arquillian Cube* you can use +portBinding+ and it will automatically set to exposed port.

In next example we are only setting +portBinding+ and *Arquillian Cube* will instruct _Docker_ to expose port 8080 and of course bind the port 8080 so it can be accessible from outside.

[source, xml]
.arquillian.xml
----
daytime:
  buildImage:
    dockerfileLocation: src/test/resources/undertow
    noCache: true
    remove: true
  await:
    strategy: polling
  portBindings: [8080/tcp]
----

Also it is not necessary to set the network protocol (tcp or udp).
If protocol is not specified `portBindings: ["8080"]` then _tcp_ is used by default.
Notice that you need to add double-quotes to stringify the value.

=== Allow connecting to a running container

With the configuration option +connectionMode+ you can bypass
the Create/Start Cube commands if the a _Docker_ Container with the same name is already
running on the target system. If so, *Arquillian Cube* will reuse that Container moving forward.

This allows you to prestart the containers manually during development and just
connect to them to avoid the extra cost of starting the _Docker_ Containers for each test
run. This assumes you are not changing the actual definition of the _Docker_ Container itself.

An example of this configuration could be:

[source, xml]
.arquillian.xml
----
<extension qualifier="docker">
  <property name="serverVersion">1.12</property>
  <property name="serverUri">http://localhost:2375</property>
  <property name="connectionMode">STARTORCONNECT</property>
  <property name="dockerContainers">
      tomcat:
        #more properties
  </property>
</extension>
----

+connectionMode+ is an attribute that can receive three parameters:

STARTANDSTOP:: it is the default one if not set any and simply creates and stops all _Docker_ Containers. If a container is already running, an exception is thrown.
STARTORCONNECT:: it tries to bypass the Create/Start Cube commands if a container with the same name is already running, and if it is the case doesn’t stop it at the end. But if container is not already running, Cube will start one and stop it at the end of the execution.
STARTORCONNECTANDLEAVE:: it is exactly the same of _STARTORCONNECT_ but if container is started by Cube it won’t be stopped at the end of the execution so it can be reused in next executions.

=== Before Stop Events

Sometimes when the tests has finished and container is stopped you want to inspect some data like container console or getting a file from the container to manual inspecting.
In these cases you can configure each container to copy console log or copy a file/s from container to local machine just before container is stopped.

Next snippet shows how to copy a directory from container to local disk:

[source, yaml]
----
tomcat_default:
  image: tutum/tomcat:7.0
  beforeStop: # <1>
    - copy: # <2>
        from: /test
        to: /tmp

    - log: # <3>
        to: /tmp/container.log
----
<1> +beforeStop+ goes into the container section and may contain a list of +copy+ and +log+ elements.
<2> +copy+ is used to notify that we want to copy some directories or files form +from+ container location to +to+ local location.
<3> +log+ is used to notify that we want to copy container log to +to+ local location.

In case of +log+ command the standard output and the error output are returned.
+log+ _Docker_ command can receive some configuration paramters and you can set them too in configuration file.

[source, yaml]
.Example of log parameters
----
beforeStop:
  - log:
    to: /tmp/container.log
    follow: true
    stdout: true
    stderr: false
    timestamps: true
    tail: 10
----

[[automatic-resolution]]
=== Automatic serverUri resolution

+serverUri+ parameter is where you configure the Uri of _Docker_ server.
This parameter is not mandatory and in case you don't set it, _Arquillian Cube_ will use next values:

[cols="2*"]
|===
|Linux
|unix:///var/run/docker.sock

|Windows
|https://dockerHost:2376

|MacOS
|https://dockerHost:2376

|Docker Machine
|https://dockerHost:2376
|===

[[boot2docker]]
== Boot2Docker and Docker Machine

If you are using _boot2docker_ or _docker machine_ there are some parameters that depends on the local installation.
For example _boot2docker_ ip is not _localhost_ and may change every time you start a new _boot2docker_ instance.
Also every time you start _boot2docker_ copies required certificates to home directory of local machine.

_Arquillian Cube_ offers some automatic mechanisms to use _boot2docker_ or _docker machine_ in _Cube_.

The first one is that +serverUri+ parameter can contain the word +dockerHost+ like for example +https://dockerHost:2376+.
When _Cube_ is started it will check if the +serverUri+ contains the _dockerHost_ word, and if it is the case it will do next things:

. if docker machine name is provided by using +machineName+ property then Docker Machine command is run to get the ip to be replaced in `dockerHost`.
. if previous conditions are not met, then _boot2docker_ command is run to get the ip to be replaced in `dockerHost`.

=== Boot2Docker

In case of _boot2docker_ it will run the command +boot2docker ip+ to get the ip and substitute the _dockerHost_ keyword to the ip returned by that command.

Note that by default _Arquillian Cube_ assumes that +boot2docker+ command is on +PATH+, but you can configure its location by using +boot2dockerPath+ property which is the full location (and program name) of _boot2docker_.
For example +/opt/boot2dockerhome/boot2docker+.

_boot2docker_ runs in _https_ and you need to set the certificates path.
These certificates are copied by _boot2docker_ by default at +<HOME>/.boot2docker/certs/boot2docker-vm+.
If this property is not set and the +serverUri+ contains +dockerHost+, then this property is automatically configured to +<HOME>/.boot2docker/certs/boot2docker-vm+ so you don't need to worry to set for each environment.

=== Docker Machine

In case of _docker-machine_ it will run the command +docker-machine ip <machineName>+ to get the ip and substitute the _dockerHost_ keyword to the ip returned by that command.

Note that by default _Arquillian Cube_ assumes that +docker-machine+ command is on +PATH+, but you can configure its location by using the +dockerMachinePath+ proeprty which is the full location (and program name too) of _docker-machine_.
For example +/usr/bin/docker-machine+..

_docker-machine_ can run with _boot2docker_ together.
And this docker host instance runs in _https_ so you need to set the certificates path.
These certificates are copied by _docker-machine_ by default at +<HOME>/.docker/machine/machines+.
If this property is not set and _docker-machine_ is run, then this property is automatically configured to default location, so you don't need to worry to set for each environment.

For example you can configure +arquillian.xml+ file to use _docker-machine_ as:

[source, xml]
.arquillian.xml
----
<extension qualifier="docker">
    <property name="serverVersion">${docker.api.version}</property>
    <property name="definitionFormat">COMPOSE</property>
    <property name="machineName">dev</property> <!-- 1 -->
    <property name="dockerContainersFile">docker-compose.yml</property>
</extension>
----
<1> Sets docker machine to _dev_.

Notice that you only need to add _machineName_ property, everything else it is exactly the same as previous examples.

== Building containers

To build a container _Docker_ uses a file called +Dockerfile+ http://docs.docker.com/reference/builder/.
*Arquillian Cube* also supports building and running a container from a +Dockerfile+.

To set that *Arquillian Cube* must build the container, the +image+ property must be changed to +buildImage+ and add the location of +Dockerfile+.

Let's see previous example but instead of creating a container from a predefined image, we are going to build one:

[source, yaml]
.arquillian.xml
----
<property name="dockerContainers">
  tomcat:
    buildImage: #1
      dockerfileLocation: src/test/resources-tomcat-7-dockerfile/tomcat #2
      noCache: true #3
      remove: true #4
      dockerfileName: my-dockerfile #5
    await:
      strategy: polling
    env: [JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
    portBindings: [8089/tcp, 8080/tcp]
</property>
----
<1> +buildImage+ section is used in front of +image+. In case of both sections present in a document, +image+ section has preference over +buildImage+.
<2> +dockerfileLocation+ contains the location of +Dockerfile+ and all files required to build the container.
<3> Property to enable or disable the no cache attribute.
<4> Property to enable or disable the remove attribute.
<5> Property to set the dockerfile name to be used instead of the default ones.

TIP: +dockerfileLocation+ can be a directory that must contains +Dockerfile+ in root directory (in case you don't set _dockerfileName_ property), also a +tar.gz+ file or a _URL_ pointing to a +tar.gz+ file.

An example of +Dockerfile+ is:

[source, properties]
.src/test/resources-tomcat-7-dockerfile/tomcat/Dockerfile
----
FROM tutum/tomcat:7.0

ENV JAVA_OPTS -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
ADD tomcat-users.xml /tomcat/conf/ # <1>
EXPOSE 8089
CMD ["/tomcat/bin/catalina.sh","run"]
----
<1> +tomcat-users.xml+ file is located at same directory as +Dockerfile+.

[[docker-compose-format]]
== Docker-Compose Format

Instead of using Arquillian Cube format, you can use Docker Compose format to define containers layout. This means that you can use the same Docker Compose file for running your tests with Arquillian Cube and without any change run `docker-compose up` command from terminal and get the same result.

It is important to note that this is not a docker-compose implementation but only the docker-compose format. This means that for example you cannot execute some CLI commands of _docker-compose_ like start several instances of same service.

In case of some specific Arquillian Cube attributes like await strategy cannot be configured and the default values are going to be used.

Moreover there are some docker-compose commands that are not implemented yet due to restrictions on docker-java library. These commands are  _pid_, _log_driver_ and _security_opt_. But they will be implemented as soon as docker-java library adds their support.

Last thing, in case you define a command that is not implemented in Arquillian Cube, this command will be ignored (no exception will be thrown), but a log line will be printed notifying this situation. Please it is really important that if this happens you open a bug so we can add support for them. Althought this warning we will try to maintain aligned with the latest docker-compose format.

Let's see how you can rewrite previous HelloWorld example with Tomcat to be used using docker-compose format.

First let's create a file called `envs` on root of the project which configures environment variables:

[source]
.envs
----
TOMCAT_PASS=<PASSWORD>
JAVA_OPTS=-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
----

Then you can create a file called `docker-compose.yml` following docker-compose commands on root of the project:

[source, yml]
.docker-compose.yml
----
tomcat:
  env_file: envs
  image: tutum/tomcat:7.0
  ports:
      - "8089:8089"
      - "8088:8088"
      - "8081:8080"
----

and finally you can configure in `arquillian.xml` file that you want to use docker-compose format.

[source, xml]
.src/test/resources/arquillian.xml
----
<extension qualifier="docker">
  <property name="serverVersion">1.13</property>
  <property name="serverUri">localhost</property>
  <property name="definitionFormat">COMPOSE</property>
  <property name="dockerContainersFile">docker-compose.yml</property>
</extension>

<container qualifier="tomcat">
  <configuration>
    <property name="host">${docker.tomcat.host}</property>
    <property name="httpPort">8081</property>
    <property name="user">admin</property>
    <property name="pass"><PASSWORD></property>
  </configuration>
</container>
----

And that's all, you can now reuse your existing docker-compose files in Arquillian Cube too.
You can see the full example at: https://github.com/arquillian/arquillian-cube/tree/master/docker/ftest-docker-compose

== Enrichers

*Arquillian Cube* comes with a few enrichers.

One for injecting the +CubeID+(_containerId_) of the current container created for executing the test, one that injects the +CubeController+ to call lifecycle methods on any cube and one that injects +com.github.dockerjava.api.DockerClient+ instance used to communicate with _Docker_ server. Also you can inject in your tests the _Docker Host IP_ used for running containers by using +@HostIp+ annotation.

DockerClient and Docker Host IP injection only work if the tests are run in client mode, that is by using +@RunAsClient+ or by setting the testable property to false +@Deployment(testable = false)+.

These can be injected using the +@ArquillianResource+ annotation.

As examples:

[source, java]
.CubeIDResourceProvider.java
----
@ArquillianResource
CubeID containerId;<commit_msg>Updates example of Docker-Compose<commit_after>= Arquillian Cube

Documentation for version Alpha6 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha6/README.adoc

Documentation for version Alpha5 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha5/README.adoc

Documentation for version Alpha4 can be found here: https://github.com/arquillian/arquillian-cube/blob/1.0.0.Alpha4/README.adoc


WARNING: 1.0.0.Alpha7 breaks incompatibility with previous versions in some cases. The major difference is that instead of using the _boot2docker_ keyword to refer to the auto resolved boot2docker ip in the _serverUri_ parameter, you should now used _dockerHost_.

== What is this?

*Arquillian Cube* is an _Arquillian_ extension that can be used to manager _Docker_ containers from _Arquillian_.

Extension is named *Cube* for two reasons:

* Because Docker is like a cube
* Because http://en.memory-alpha.org/wiki/Borg_cube[Borg starship] is named *cube* and well because we are moving tests close to production we can say that "any resistance is futile, bugs will be assimilated".

With this extension you can start a _Docker_ container with a server installed, deploy the required deployable file within it and execute _Arquillian_ tests.

The key point here is that if _Docker_ is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before.

But it also lets you start a container with every required service like database, mail server, ... and instead of stubbing or using fake objects your tests can use real servers.

[WARNING]
====
This extension has been developed and tested on a Linux machine with the _Docker_ server already installed.
It works with *Boot2Docker* as well in _Windows_ and _MacOS_ machines, but some parameters like _host ip_ must be the _Boot2Docker_ server instead of _localhost_ (in case you have _Docker_ server installed inside your own machine).

One of the best resources to learn about why using _Boot2Docker_ is different from using _Docker_ in Linux can be read here http://viget.com/extend/how-to-use-docker-on-os-x-the-missing-guide
====

== Preliminaries

*Arquillian Cube* relies on https://github.com/docker-java/docker-java[docker-java] API.

To use *Arquillian Cube* you need a _Docker_ daemon running on a computer (it can be local or not), but probably it will be at local.

By default the _Docker_ server uses UNIX sockets for communicating with the _Docker_ client. *Arquillian Cube* will attempt to detect the operating system it is running on and either set _docker-java_ to use UNIX socket on _Linux_ or to <<Boot2Docker>> on _Windows_/_Mac_ as the default URI.

If you want to use TCP/IP to connect to the Docker server, you'll need to make sure that your _Docker_ server is listening on TCP port.
To allow _Docker_ server to use TCP add the following line to +/etc/default/docker+:

+DOCKER_OPTS="-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"+

After restarting the _Docker_ daemon you need to make sure that _Docker_ is up and listening on TCP.

[source, terminal]
----
$ docker -H tcp://127.0.0.1:2375 version

Client version: 0.8.0
Go version (client): go1.2
Git commit (client): cc3a8c8
Server version: 1.2.0
Git commit (server): fa7b24f
Go version (server): go1.3.1
----

If you cannot see the client and server versions then it means that something is wrong with the _Docker_ installation.

== Basic Example

After having a _Docker_ server installed we can start using *Arquillian Cube*.
In this case we are going to use a very simple example using a _Docker_ image with _Apache Tomcat_ and we are going to test a _Servlet_ on it.

[source, java]
.HelloWorldServlet.java
----
@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("Hello World");
  }
}
----

[source, java]
.HelloWorldServletTest.java
----
@RunWith(Arquillian.class)
public class HelloWorldServletTest {

  @Deployment(testable=false) //<1>
  public static WebArchive create() {
    return ShrinkWrap.create(WebArchive.class, "hello.war").addClass(HelloWorldServlet.class); //<2>
  }

  @Test
  public void should_parse_and_load_configuration_file(@ArquillianResource URL resource) throws IOException { //<3>

    URL obj = new URL(resource, "HelloWorld");
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");

    BufferedReader in = new BufferedReader(
            new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    assertThat(response.toString(), is("Hello World"));//<4>
  }
}
----
<1> In this case we are running the test as a client. So in fact this test is executed against the container instead of inside the container.
<2> No changes in this part, we need to create a deployable file, and because we are testing against _Tomcat_, a _war_ file is created.
<3> Because the test is run as client, we can use +@ArquillianResource+ to get the URL where the file is deployed. Note that this will be the URL to access _Tomcat_ running inside the _Docker_ container.
<4> Typical jUnit assertion of servlet response.

Now this test could be run in any container, there is nothing that ties this to _Docker_.
Next step is adding some dependencies apart from the typical _Arquillian_ dependencies.

[source, xml]
.pom.xml
----
<dependency>
  <groupId>org.arquillian.cube</groupId>
  <artifactId>arquillian-cube-docker</artifactId> <!--1-->
  <version>${project.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.jboss.arquillian.container</groupId>
  <artifactId>arquillian-tomcat-remote-7</artifactId> <!--2-->
  <version>1.0.0.CR7</version>
  <scope>test</scope>
</dependency>
----
<1> Adds *Arquillian Cube* dependency.
<2> From the point of view of _Arquillian_, _Tomcat_ is being executed in a remote host (in fact this is true because _Tomcat_ is running inside _Docker_ which is external to _Arquillian_), so we need to add the remote adapter.

And finally we need to configure _Tomcat_ remote adapter and *Arquillian Cube* in +arquillian.xml+ file.

[source, xml]
.arquillian.xml
----
<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://jboss.org/schema/arquillian"
  xsi:schemaLocation="http://jboss.org/schema/arquillian
  http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

  <extension qualifier="docker"> <!--1-->
      <property name="serverVersion">1.12</property> <!--2-->
      <property name="serverUri">http://localhost:2375</property> <!--3-->
      <property name="dockerContainers"> <!--4-->
          tomcat:
            image: tutum/tomcat:7.0
            exposedPorts: [8089/tcp]
            await:
              strategy: polling
            env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
            portBindings: [8089/tcp, 8080/tcp]
      </property>
  </extension>

  <container qualifier="tomcat" default="true"> <!--5-->
      <configuration>
          <property name="host">localhost</property> <!--6-->
          <property name="httpPort">8080</property> <!--7-->
          <property name="user">admin</property> <!--8-->
          <property name="pass"><PASSWORD></property>
      </configuration>
  </container>

</arquillian>
----
<1> *Arquillian Cube* extension is registered.
<2> _Docker_ server version is required.
<3> _Docker_ server URI is required. In case you are using a remote _Docker_ host or _Boot2Docker_ here you need to set the remote host ip, but in this case _Docker_ server is on same machine.
<4> A _Docker_ container contains a lot of parameters that can be configured. To avoid having to create one XML property for each one, a YAML content can be embedded directly as property.
<5> Configuration of _Tomcat_ remote adapter. Cube will start the _Docker_ container when it is ran in the same context as an _Arquillian_ container with the same name.
<6> Host can be _localhost_ because there is a port forwarding between container and _Docker_ server.
<7> Port is exposed as well.
<8> User and password are required to deploy the war file to remote _Tomcat_.

And that's all.
Now you can run your test and you will see how _tutum/tomcat:7.0_ image is downloaded and started.
Ports 8080 (Tomcat standard port) and 8089(JMX port used by Arquillian) are exposed.
Finally in _env_ section, environment variables are set. Read next link to understand why this is required https://docs.jboss.org/author/display/ARQ/Tomcat+7.0+-+Remote

== Configuration

*Arquillian Cube* requires some parameters to be configured, some related with _Docker_ server and others related on the image that is being used.
Let's see valid attributes:

[cols="2*"]
|===
|serverVersion
|Version of REST API provided by_Docker_ server. You should check on the _Docker_ site which version of REST API is shipped inside installed _Docker_ service. This field is not mandatory and if it's not set the default provided version from _docker-java_ will be used.

|serverUri
|Uri of _Docker_ server. If the _Docker_ server is running natively on Linux then this will be an URI pointing to _localhost_ docker host but if you are using _Boot2Docker_ or a remote _Docker_ server then the URI should be changed to point to the _Docker_ remote _URI_. It can be a unix socket URI as well in case you are running _Docker_ on Linux (+unix:///var/run/docker.sock+). Also you can read at <<automatic-resolution, this section>> about automatic resolution of serverUri parameter. Also you can use `DOCKER_HOST` java property or system environment to set this parameter.

|dockerRegistry
|Sets the location of Docker registry. Default value is the official _Docker_ registry located at https://registry.hub.docker.com

|username
|Sets the username to connect to Docker registry.

|password
|Sets the password to connect to Docker registry.

|dockerContainers
|Each _Docker_ image (or container) can be configured with different parameters. This configuration is provided in YAML format. This property can be used to embed as YAML string value, all configuration.

|dockerContainersFile
|Instead of embedding YAML as a string, you can set the location of a YAML file with this attribute. The location can be a relative from the root of the project or also a URI that is converted to URL so you can effectively have docker definitions on remote sites.

|definitionFormat
|Sets the format of content expressed in `dockerContainers` attribute or in file set in `dockerContainersFile`. It can contain two possible values _CUBE_ (default one in case of not set) to indicate that content is written following <<cube-format, Arquillian Cube>> format or _COMPOSE_ to indicate that content is written following <<docker-compose-format, Docker Compose>> format.

|autoStartContainers
|Cube will normally start a _Docker_ container when it has the same name as an active _Arquillian_ container and all the containers defined as links to this container, so basically _Cube_ resolves all the container depdendencies as well e.g. a database where the application saves data, or mail server where application sends an email. That works for things that are _DeployableContainer_'s. For any other container services that might not have a link to the _DeployableContainer_, e.g. a monitor, you can use the _autoStartContainers_ option to define which _Docker_ containers to automatically start up. The option takes a comma separated list of _Docker_ container ids. e.g. _monitor_. *Arquillian Cube* will attempt to start the containers in parallel if possible as well as start any linked containers. Also if you need to start several images, instead of adding them as CSV, you can use a regular expression by prefixing with `regexp:`, for example setting the property to `regexp:a(.*)` would start all container ids starting with _a_. 

|certPath
|Path where certificates are stored. If you are not using _https_ protocol this parameter is not required. This parameter accepts starting with ~ as home directory

|boot2dockerPath
|Sets the full location (and program name) of _boot2docker_. For example +/opt/boot2dockerhome/boot2docker+.

|dockerMachinePath
|Sets the full location (and program name) of _docker-machine_. For example +/opt/dockermachinehome/docker-machine+.

|machineName
|Sets the machine name in case you are using docker-machine to manage your docker host. This parameter is mandatory when using docker-machine.

|connectionMode
|Connection Mode to bypass the Create/Start Cube commands if the a Docker Container with the same name is already running on the target system. This parameter can receive three possible values. _STARTANDSTOP_ which is the default one if not set any and simply creates and stops all Docker Containers. If a container is already running, an exception is thrown. _STARTORCONNECT_ mode tries to bypass the Create/Start Cube commands if a container with the same name is already running, and if it is the case doesn’t stop it at the end. But if container is not already running, Cube will start one and stop it at the end of the execution. And last mode is _STARTORCONNECTANDLEAVE_ which is exactly the same of _STARTORCONNECT_ but if container is started by Cube it won’t be stopped at the end of the execution so it can be reused in next executions.
|===

Some of these properties can be provided by using standard Docker system environment variables so you can set once and use them in your tests too.
Moreover you can set as Java system properties (-D...) as well.

[cols="2*"]
|===
|serverUri
|DOCKER_HOST

|certPath
|DOCKER_CERT_PATH

|machineName
|DOCKER_MACHINE_NAME
|===

In the next example you can see a whole YAML document with configuration properties.
Keep in mind that almost all of them are configuration parameters provided by _Docker_ remote API.
In this example we are going to explain the attributes that are most used and special cases.
Of course not all of them are mandatory:

NOTE: In YAML adding brackets ("[" "]") is for setting a list.

[[cube-format]]
[source, yaml]
----
tomcat: #1
  image: tutum/tomcat:7.0 #2
  exposedPorts: [8089/tcp] #3
  await: #4
    strategy: polling #5
  workingDir: .
  alwaysPull: false
  disableNetwork: true
  hostName: host
  portSpecs: [80,81]
  user: alex
  tty: true
  stdinOpen: true
  stdinOnce: true
  memoryLimit: 1
  memorySwap: 1
  cpuShares: 1
  cpuSet: a
  extraHosts: a
  attachStdin: true
  attachStderr: true
  env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089] #6
  cmd: [] #7
  dns: [127.0.0.1]
  volumes: [/tmp]
  volumesFrom: [tomcat]
  binds:
    - /host:/container:ro
  links:
    - name:alias
    - name2:alias2
  portBindings: [8089/tcp, 8081->8080/tcp] #8
  privileged: true
  publishAllPorts: true
  networkMode: host
  dnsSearch: [127.0.0.1]
  entryPoint: [sh]
  devices:
    cGroupPermissions: a
    pathOnHost: b
    pathInContainer: c
  restartPolicy: #10
    name: failure
    maximumRetryCount: 1
  capAdd: [a]
  capDrop: [b]
  extends: container-id #9
----
<1> The name that are going to be assign to running container. It is *mandatory*.
<2> The name of the image to be used. It is *mandatory*. If the image has not already been pulled by the _Docker_ server, *Arquillian Cube* will pull it for you. If you want to always pull latest image before container is created, you can configure *alwaysPull: true*.
<3> Sets exposed ports of the running container. It should follow the format _port number_ slash(/) and _protocol (udp or tcp). Note that it is a list and it is not mandatory.
<4> After a container is started, it starts booting up the defined services/commands. Depending on the nature of service, the lifecycle of these services are linked to start up or not. For example Tomcat, Wildlfy, TomEE and in general all Java servers must be started in foreground and this means that from the point of view of the client, the container never finishes to start. But on the other side other services like Redis are started in background and when the container is started you can be sure that Redis server is there. To avoid executing tests before the services are ready, you can set which await strategy should be used from *Arquillian Cube* side to accept that _Docker_ container and all its defined services are up and ready. It is not mandatory and by default polling with _ss_ command strategy is used.
<5> In +strategy+ you set which strategy you want to follow. Currently three strategies are supported. _static_, _native_ and _polling_.
<6> You can pass environment variables by using `env`. In this section you can set special `dockerServerIp` string which at runtime will be replaced by _Cube_ to current docker server ip.
<7> After the container is up, a list of commands can be executed within it.
<8> Port forwarding is configured using `portBinding` section. It contains a list of `exposedPort` and `port` separated by arrow (_->_). If only one port is provided, *Arquillian Cube* will expose the same port number. In this example the exposed port 8089 is mapped to 8089 and exposed port 8080 is mapped to 8081.
<9> You can extend another configuration. Any top level element and it's children from the target container-id will be copied over to this configuration, unless they have been defined here already.

As we've seen in the basic example the definition of the Arquillian Cube scenarios are described in `dockerContainers` property.
But if you want you can avoid using this property by simply creating a file called `cube` in the root of the classpath of your project.
_Arquillian Cube_ will read it as if it was defined in `arquilllian.xml` file.

[source, yaml]
.src/test/resources/cube
----
tomcat:
  image: tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: polling
  env: [TOMCAT_PASS=<PASSWORD>, JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
  portBindings: [8089/tcp, 8080/tcp]
----

=== Await

After a container is started, it starts booting up the defined services/commands.
Depending on the nature of service, the lifecycle of these services are linked to start up or not.
For example Tomcat, Wildlfy, TomEE and in general all Java servers must be started in foreground and this means that from the point of view of the _Docker_ client, the container never finishes to start.
But on the other side other services like Redis are started in background and when the container is started you can be sure that Redis server is there.
To avoid executing tests before the services are ready, you can set which await strategy should be used from *Arquillian Cube* side to accept that _Docker_ container and all its defined services are up and ready.

Currently next await strategies are supported:

native:: it uses *wait* command. In this case current thread is waiting until the _Docker_ server notifies that has started. In case of foreground services this is not the approach to be used.
polling:: in this case a polling (with _ping_ or _ss_ command) is executed for 5 seconds against all exposed ports. When communication to all exposed ports is acknowledged, the container is considered to be up. This approach is the one to be used in case of services started in foreground. By default _polling_ executes _ss_ command inside the running container to know if the server is already running. You can use a _ping_ from client by setting +type+ attribute to +ping+; Note that _ping_ only works if you are running _Docker_ daemon on +localhost+. In almost all cases the default behaviour matches all scenarios. If it is not specified, this is the default strategy.
static:: similar to _polling_ but it uses the host ip and specified list of ports provided as configuration parameter. This can be used in case of using _Boot2Docker_.
sleeping:: sleeps current thread for the specified amount of time. You can specify the time in seconds or milliseconds.

By default in case you don't specify any _await_ strategy, polling with _ss_ command is used.

[source, yaml]
.Example native
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: native
----

[source, yaml]
.Example polling using ss command by default
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: polling
    sleepPollingTime: 200 s #1
    iterations: 3 #2
----
<1> Optional parameter to configure sleeping time between poling. You can set in seconds using _s_ or miliseconds using _ms_. By default time unit is miliseconds and value 500.
<2> Optional parameter to configure number of retries to be done. By default 10 iterations are done.

[source, yaml]
.Example static
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: static
    ip: localhost
    ports: [8080, 8089]
----

[source, yaml]
.Example sleeping
----
tomcat:
  image: tutum/tomcat:7.0
  exposedPorts: [8089/tcp]
  await:
    strategy: sleeping
    sleepTime: 200 s #1
----
<1> Optional parameter to configure sleeping time between poling. You can set in seconds using _s_ or miliseconds using _ms_. By default time unit is miliseconds and value 500.

=== Inferring exposedPorts from portBinding

When you are using _Docker_ you can set two different parameters, +exposedPort+ and +portBinding+.
+exposedPorts+ are ports that are available inside _Docker_ infrastructure and they are used for communication between _Docker_ containers but not from outside.
On the other side +portBindings+ are a way to instruct _Docker_ container to publish a port to be available from outside (for example from our test).

It seems reasonable that if you set a port binding this port should automatically be exposed port as well.
For this reason in *Arquillian Cube* you can use +portBinding+ and it will automatically set to exposed port.

In next example we are only setting +portBinding+ and *Arquillian Cube* will instruct _Docker_ to expose port 8080 and of course bind the port 8080 so it can be accessible from outside.

[source, xml]
.arquillian.xml
----
daytime:
  buildImage:
    dockerfileLocation: src/test/resources/undertow
    noCache: true
    remove: true
  await:
    strategy: polling
  portBindings: [8080/tcp]
----

Also it is not necessary to set the network protocol (tcp or udp).
If protocol is not specified `portBindings: ["8080"]` then _tcp_ is used by default.
Notice that you need to add double-quotes to stringify the value.

=== Allow connecting to a running container

With the configuration option +connectionMode+ you can bypass
the Create/Start Cube commands if the a _Docker_ Container with the same name is already
running on the target system. If so, *Arquillian Cube* will reuse that Container moving forward.

This allows you to prestart the containers manually during development and just
connect to them to avoid the extra cost of starting the _Docker_ Containers for each test
run. This assumes you are not changing the actual definition of the _Docker_ Container itself.

An example of this configuration could be:

[source, xml]
.arquillian.xml
----
<extension qualifier="docker">
  <property name="serverVersion">1.12</property>
  <property name="serverUri">http://localhost:2375</property>
  <property name="connectionMode">STARTORCONNECT</property>
  <property name="dockerContainers">
      tomcat:
        #more properties
  </property>
</extension>
----

+connectionMode+ is an attribute that can receive three parameters:

STARTANDSTOP:: it is the default one if not set any and simply creates and stops all _Docker_ Containers. If a container is already running, an exception is thrown.
STARTORCONNECT:: it tries to bypass the Create/Start Cube commands if a container with the same name is already running, and if it is the case doesn’t stop it at the end. But if container is not already running, Cube will start one and stop it at the end of the execution.
STARTORCONNECTANDLEAVE:: it is exactly the same of _STARTORCONNECT_ but if container is started by Cube it won’t be stopped at the end of the execution so it can be reused in next executions.

=== Before Stop Events

Sometimes when the tests has finished and container is stopped you want to inspect some data like container console or getting a file from the container to manual inspecting.
In these cases you can configure each container to copy console log or copy a file/s from container to local machine just before container is stopped.

Next snippet shows how to copy a directory from container to local disk:

[source, yaml]
----
tomcat_default:
  image: tutum/tomcat:7.0
  beforeStop: # <1>
    - copy: # <2>
        from: /test
        to: /tmp

    - log: # <3>
        to: /tmp/container.log
----
<1> +beforeStop+ goes into the container section and may contain a list of +copy+ and +log+ elements.
<2> +copy+ is used to notify that we want to copy some directories or files form +from+ container location to +to+ local location.
<3> +log+ is used to notify that we want to copy container log to +to+ local location.

In case of +log+ command the standard output and the error output are returned.
+log+ _Docker_ command can receive some configuration paramters and you can set them too in configuration file.

[source, yaml]
.Example of log parameters
----
beforeStop:
  - log:
    to: /tmp/container.log
    follow: true
    stdout: true
    stderr: false
    timestamps: true
    tail: 10
----

[[automatic-resolution]]
=== Automatic serverUri resolution

+serverUri+ parameter is where you configure the Uri of _Docker_ server.
This parameter is not mandatory and in case you don't set it, _Arquillian Cube_ will use next values:

[cols="2*"]
|===
|Linux
|unix:///var/run/docker.sock

|Windows
|https://dockerHost:2376

|MacOS
|https://dockerHost:2376

|Docker Machine
|https://dockerHost:2376
|===

[[boot2docker]]
== Boot2Docker and Docker Machine

If you are using _boot2docker_ or _docker machine_ there are some parameters that depends on the local installation.
For example _boot2docker_ ip is not _localhost_ and may change every time you start a new _boot2docker_ instance.
Also every time you start _boot2docker_ copies required certificates to home directory of local machine.

_Arquillian Cube_ offers some automatic mechanisms to use _boot2docker_ or _docker machine_ in _Cube_.

The first one is that +serverUri+ parameter can contain the word +dockerHost+ like for example +https://dockerHost:2376+.
When _Cube_ is started it will check if the +serverUri+ contains the _dockerHost_ word, and if it is the case it will do next things:

. if docker machine name is provided by using +machineName+ property then Docker Machine command is run to get the ip to be replaced in `dockerHost`.
. if previous conditions are not met, then _boot2docker_ command is run to get the ip to be replaced in `dockerHost`.

=== Boot2Docker

In case of _boot2docker_ it will run the command +boot2docker ip+ to get the ip and substitute the _dockerHost_ keyword to the ip returned by that command.

Note that by default _Arquillian Cube_ assumes that +boot2docker+ command is on +PATH+, but you can configure its location by using +boot2dockerPath+ property which is the full location (and program name) of _boot2docker_.
For example +/opt/boot2dockerhome/boot2docker+.

_boot2docker_ runs in _https_ and you need to set the certificates path.
These certificates are copied by _boot2docker_ by default at +<HOME>/.boot2docker/certs/boot2docker-vm+.
If this property is not set and the +serverUri+ contains +dockerHost+, then this property is automatically configured to +<HOME>/.boot2docker/certs/boot2docker-vm+ so you don't need to worry to set for each environment.

=== Docker Machine

In case of _docker-machine_ it will run the command +docker-machine ip <machineName>+ to get the ip and substitute the _dockerHost_ keyword to the ip returned by that command.

Note that by default _Arquillian Cube_ assumes that +docker-machine+ command is on +PATH+, but you can configure its location by using the +dockerMachinePath+ proeprty which is the full location (and program name too) of _docker-machine_.
For example +/usr/bin/docker-machine+..

_docker-machine_ can run with _boot2docker_ together.
And this docker host instance runs in _https_ so you need to set the certificates path.
These certificates are copied by _docker-machine_ by default at +<HOME>/.docker/machine/machines+.
If this property is not set and _docker-machine_ is run, then this property is automatically configured to default location, so you don't need to worry to set for each environment.

For example you can configure +arquillian.xml+ file to use _docker-machine_ as:

[source, xml]
.arquillian.xml
----
<extension qualifier="docker">
    <property name="serverVersion">${docker.api.version}</property>
    <property name="definitionFormat">COMPOSE</property>
    <property name="machineName">dev</property> <!-- 1 -->
    <property name="dockerContainersFile">docker-compose.yml</property>
</extension>
----
<1> Sets docker machine to _dev_.

Notice that you only need to add _machineName_ property, everything else it is exactly the same as previous examples.

== Building containers

To build a container _Docker_ uses a file called +Dockerfile+ http://docs.docker.com/reference/builder/.
*Arquillian Cube* also supports building and running a container from a +Dockerfile+.

To set that *Arquillian Cube* must build the container, the +image+ property must be changed to +buildImage+ and add the location of +Dockerfile+.

Let's see previous example but instead of creating a container from a predefined image, we are going to build one:

[source, yaml]
.arquillian.xml
----
<property name="dockerContainers">
  tomcat:
    buildImage: #1
      dockerfileLocation: src/test/resources-tomcat-7-dockerfile/tomcat #2
      noCache: true #3
      remove: true #4
      dockerfileName: my-dockerfile #5
    await:
      strategy: polling
    env: [JAVA_OPTS=-Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false]
    portBindings: [8089/tcp, 8080/tcp]
</property>
----
<1> +buildImage+ section is used in front of +image+. In case of both sections present in a document, +image+ section has preference over +buildImage+.
<2> +dockerfileLocation+ contains the location of +Dockerfile+ and all files required to build the container.
<3> Property to enable or disable the no cache attribute.
<4> Property to enable or disable the remove attribute.
<5> Property to set the dockerfile name to be used instead of the default ones.

TIP: +dockerfileLocation+ can be a directory that must contains +Dockerfile+ in root directory (in case you don't set _dockerfileName_ property), also a +tar.gz+ file or a _URL_ pointing to a +tar.gz+ file.

An example of +Dockerfile+ is:

[source, properties]
.src/test/resources-tomcat-7-dockerfile/tomcat/Dockerfile
----
FROM tutum/tomcat:7.0

ENV JAVA_OPTS -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
ADD tomcat-users.xml /tomcat/conf/ # <1>
EXPOSE 8089
CMD ["/tomcat/bin/catalina.sh","run"]
----
<1> +tomcat-users.xml+ file is located at same directory as +Dockerfile+.

[[docker-compose-format]]
== Docker-Compose Format

Instead of using Arquillian Cube format, you can use Docker Compose format to define containers layout. This means that you can use the same Docker Compose file for running your tests with Arquillian Cube and without any change run `docker-compose up` command from terminal and get the same result.

It is important to note that this is not a docker-compose implementation but only the docker-compose format. This means that for example you cannot execute some CLI commands of _docker-compose_ like start several instances of same service.

In case of some specific Arquillian Cube attributes like await strategy cannot be configured and the default values are going to be used.

Moreover there are some docker-compose commands that are not implemented yet due to restrictions on docker-java library. These commands are  _pid_, _log_driver_ and _security_opt_. But they will be implemented as soon as docker-java library adds their support.

Last thing, in case you define a command that is not implemented in Arquillian Cube, this command will be ignored (no exception will be thrown), but a log line will be printed notifying this situation. Please it is really important that if this happens you open a bug so we can add support for them. Althought this warning we will try to maintain aligned with the latest docker-compose format.

Let's see how you can rewrite previous HelloWorld example with Tomcat to be used using docker-compose format.

First let's create a file called `envs` on root of the project which configures environment variables:

[source]
.envs
----
TOMCAT_PASS=<PASSWORD>
JAVA_OPTS=-Djava.rmi.server.hostname=dockerServerIp -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
----

IMPORTANT: You can use `dockerServerIp` as special tag for identify the docker host IP. Before injecting the environement variables, Cube will change it to real host IP.

Then you can create a file called `docker-compose.yml` following docker-compose commands on root of the project:

[source, yml]
.docker-compose.yml
----
tomcat:
  env_file: envs
  image: tutum/tomcat:7.0
  ports:
      - "8089:8089"
      - "8088:8088"
      - "8081:8080"
----

and finally you can configure in `arquillian.xml` file that you want to use docker-compose format.

[source, xml]
.src/test/resources/arquillian.xml
----
<extension qualifier="docker">
  <property name="serverVersion">1.13</property>
  <property name="serverUri">localhost</property>
  <property name="definitionFormat">COMPOSE</property>
  <property name="dockerContainersFile">docker-compose.yml</property>
</extension>

<container qualifier="tomcat">
  <configuration>
    <property name="user">admin</property>
    <property name="pass"><PASSWORD></property>
  </configuration>
</container>
----

And that's all, you can now reuse your existing docker-compose files in Arquillian Cube too.
You can see the full example at: https://github.com/arquillian/arquillian-cube/tree/master/docker/ftest-docker-compose

== Enrichers

*Arquillian Cube* comes with a few enrichers.

One for injecting the +CubeID+(_containerId_) of the current container created for executing the test, one that injects the +CubeController+ to call lifecycle methods on any cube and one that injects +com.github.dockerjava.api.DockerClient+ instance used to communicate with _Docker_ server. Also you can inject in your tests the _Docker Host IP_ used for running containers by using +@HostIp+ annotation.

DockerClient and Docker Host IP injection only work if the tests are run in client mode, that is by using +@RunAsClient+ or by setting the testable property to false +@Deployment(testable = false)+.

These can be injected using the +@ArquillianResource+ annotation.

As examples:

[source, java]
.CubeIDResourceProvider.java
----
@ArquillianResource
CubeID containerId;
{'fraction_non_alphanumeric': 0.07267389024816498, 'fraction_numerical': 0.012750786438308284, 'mean_word_length': 4.27828204560549, 'pattern_counts': {'":': 0, '<': 319, '<?xml version=': 2, '>': 323, 'https://': 22, 'lorem ipsum': 0, 'www.': 2, 'xml': 44}, 'pii_count': 8, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2516562', 'n_tokens_mistral': 20828, 'n_tokens_neox': 19702, 'n_words': 9571}