README.md

# Docker Build Clone using Elixir

[![Build Status](https://travis-ci.org/esl/ex_docker_build.svg?branch=master)](https://travis-ci.org/esl/ex_docker_build)
[![Coverage Status](https://coveralls.io/repos/github/esl/ex_docker_build/badge.svg)](https://coveralls.io/github/esl/ex_docker_build)

## What's the special thing about this?

This comes with support for **Bind Mounts at Build Time**

![Bind Mount at Build Time](https://user-images.githubusercontent.com/31992054/46028189-d2b73300-c0e7-11e8-9c78-3575f652bc98.png)

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `ex_docker_build` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:ex_docker_build, "~> 0.6.2"}
  ]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/ex_docker_build](https://hexdocs.pm/ex_docker_build).

## Usage

### Example 1 - **Elixir Release with Distillery**

Clone the following example in a directory you wish

```sh
$> mkdir ~/workspace
$> cd workspace
$> git clone https://github.com/sescobb27/elixir-docker-guide
```

Start a mix session with `iex -S mix` and type the following instructions

```ex
path = Path.expand("~/workspace/elixir-docker-guide")

{:ok, image_id} = Path.join([path, "Dockerfile"]) |>
  ExDockerBuild.DockerfileParser.parse_file!() |>
  ExDockerBuild.DockerBuild.build(path)
```

Or you can start using escript:

```ex
mix escript.build
Generated escript ex_docker_build
```

Then call the escript passing the path to a Dockerfile

```ex
./ex_docker_build ~/workspace/elixir-docker-guide/Dockerfile

[info]  image created d44264c48dad
```

Copy the image_id into your clipboard and run the image with docker like this

```sh
docker run d44264c48dad # d44264c48dad being the image_id
```

### Example 2 - **Docker Build with Bind Mount**

in `test/fixtures/Dockerfile_bind.dockerfile` in line 2 `VOLUME /Users/kiro/test:/data`
change `/Users/kiro/test` with your path of preference e.g `/Your/User/test`
(must be an absolute path, relative paths aren't supported yet)

```sh
$> mkdir ~/test
```

```ex
path = Path.expand("./test/fixtures")

{:ok, image_id} = Path.join([path, "Dockerfile_bind.dockerfile"]) |>
  ExDockerBuild.DockerfileParser.parse_file!() |>
  ExDockerBuild.DockerBuild.build(path)
```

Then if you run `ls ~/test` you should see a file named `myfile.txt` with
`hello world!!!` as content

## Environment and debugging

This library respects the environmental variable `DOCKER_HOST` this can be
very helpful when debugging, for example:

In on terminal run `socat` :

```
socat -v UNIX-LISTEN:/tmp/fake,fork UNIX-CONNECT:/var/run/docker.sock
```

In the terminal where you are running `ex_docker_build` set the docker socket :

```
export DOCKER_HOST=unix:///tmp/fake
```

Now you can observe all interactions with the Docker API server.

## Limitations

- Doesn't support relative paths in the container when `COPY`ing
  - `COPY ./relative/path/to/origin:/absolute/path/to/destination`
- Doesn't support standard `VOLUMES`, it only supports the following `VOLUME`s type
  with custom syntax
  - [Bind Mounts](https://docs.docker.com/storage/bind-mounts/) e.g `VOLUME ~/path/to/host/dir:/path/to/container/dir`
  - [Named Volumes](https://docs.docker.com/storage/volumes/) e.g `VOLUME volume_name` and then using it like `VOLUME volume_name:/path/to/container/dir`

## TODO:

- [ ] add support for more docker file instructions
- [ ] resolve TODOs inside the source code