Building an image

Wercker now supports the following two ways of creating Docker images:

  • Using a Dockerfile
  • Using steps

Creating a Docker image using a Dockerfile

The internal/docker-build step allows you to build a docker image using a Dockerfile. This will be the preferred choice for users who already have a Dockerfile, or who wish to specify how to build the image in the standard docker way. Once you have built the image you can then use the internal/docker-push step to push it to an external image registry.

The internal/docker-build step builds a new Docker image from a Dockerfile. The new image is created from the base image specified in the Dockerfile and contains only those files which were provided by the base image or which were created using instructions such as ADD or RUN in the Dockerfile. This step does not change the state of the currently executing pipeline container, but creates a new image which is temporarily stored in the Docker daemon. The newly created image is identified by an image-name that you specify.

The build’s context is the set of files in the $WERCKER_ROOT directory of the currently-running pipeline container. The Dockerfile is by default expected to be in the root directory of the build context. You can use the dockerfile property to specify a different path or a different name.

For example, the following step creates a new image in the local docker daemon:

- internal/docker-build:
    dockerfile: Dockerfile 
    image-name: my-new-image

Properties

The internal/docker-build step supports the following properties:

  • dockerfile: Specifies the path within the build context to the Dockerfile. If this property is not specified, then Dockerfile is used.
  • image-name: A name that can be used in a subsequent docker-run or docker-push step to refer to the image created using the docker-build step.
  • g: Used to suppress verbose build output. The default value is false.
  • build-args: A list of build-time variables in the following format: "VAR=value" "VAR2=value2". The name-value pairs must be separated by a space. You should pass these values at build-time. This is the method to pass variables to the Dockerfile.
  • labels: Specifies a set of arbitrary key-value labels that are set on an image in the following format: label=value. The values must be separated by spaces. The resulting string must be enclosed in double quotes ("). If the key or the value contains spaces, you must enclose it in single quotes ('). Example: "Label1=value1 'Three word key'=value2 Label3='Three word value'".
  • no-cache: Set to true to prevent the use of the cache when building the image. The default value is false.
  • registry-auth-config: If the dockerfile specifies images that are in private repositories then this property should be used to specify the username and password to use for each repository. This information is supplied in JSON format as shown in the example below.

The following example shows how to specify registry usernames and passwords:

internal/docker-build:
  dockerfile: Dockerfile
  image-name: myImage
  registry-auth-config: |
    {
      "docker.example.com": {
        "username": "janedoe",
        "password": "hunter2"
    },
      "https://index.docker.io/v1/": {
        "username": "mobydock",
        "password": "conta1n3rize14"
    }
  }

When specifying the registry, only the registry domain name (and port if not the default 443) are required. However, for legacy reasons, the Docker Hub registry must be specified with both a https:// prefix and a /v1/ suffix even though Docker will prefer to use the v2 registry API. (This information is taken from the Docker documentation)

Creating a Docker image using Wercker steps

An alternative way to build a Docker image is to execute a series of steps in a Wercker pipeline and then use the internal/docker-push or the internal/docker-scratch-push step to convert the current container into a docker image and push it to an external image registry. The new image contains the result of all the steps that have been executed until that point. This approach allows you to make use of Wercker steps, including those defined in a step registry.

The internal/docker-push step allows you to create an image from the current pipeline and then immediately push that image to a docker image registry. For more information see, internal/docker-push.

The internal/docker-scratch-push step allows you to create an image from the current pipeline with a scratch base image and immediately push that image to a docker image registry. This requires some additional steps, but results in a smaller image. For more information, see internal/docker-scratch-push.

Pushing an image to a registry using Docker command

Prerequisite:

Sign in to the DockerHub image registry. Set the following environment variables to hold your Docker Hub user name and password:

export X_USERNAME=
export X_PASSWORD=

To push the image to a registry, run the following commands:

docker login -u $X_USERNAME -p $X_PASSWORD
docker tag my-image $X_USERNAME/docker-build-golang:latest
docker push $X_USERNAME/docker-build-golang

Example wercker.yml for building and pushing an image using a Dockerfile Here’s an example of wercker.yml that uses the internal/docker-build step to build an image from a Dockerfile and then uses an extended internal/docker-push step to push it to an image registry:

build:
  box: google/golang
  steps:
    # Test the project
    - script:
        name: Run tests
        code: go test ./...     
    - internal/docker-build: 
        dockerfile: Dockerfile 
        image-name: my-new-image # temporary name used to refer to this image in a subsequent step
    - internal/docker-push: 
        image-name: my-new-image
        username: $USERNAME # Docker Hub username. When using CLI, set using "export X_USERNAME="  
        password: $PASSWORD # Docker Hub password. When using CLI, set using "export X_PASSWORD=" 
        registry: https://hub.docker.com
        repository: $USERNAME/docker-build-golang
        tag: latest

This defines a Wercker pipeline called build that:

  • runs some tests
  • uses the internal/docker-build step to build the image using a Dockerfile
  • uses the internal/docker-push step to tag the image and push it to the image registry

Note: If you don’t push the new image to the registry, then the image will become inaccessible when the pipeline ends.

Pushing an image to a registry

The internal/docker-push step can be used in two ways.

You can use it to push an image that has been built using the internal/docker-build step to a Docker registry. You must set the image-name property to identify the image you wish to push, as shown in the following example. This example uses Docker Hub; but you can use any image registry.

- internal/docker-push:
    # specify the image to be pushed - this is the one we created earlier
    image-name: my-new-image 
    username: $USERNAME # Registry username  
    password: $PASSWORD # Registry password
    registry: https://hub.docker.com
    repository: $USERNAME/docker-build-golang

Alternatively, you can use this step to create a new image from the currently running container, and immediately push that image to an image registry. In this case the image-name property is not set.

Properties

The internal/docker-push step supports the following properties:

  • image-name: This property is only used when pushing an image created previously using a docker-build step. It specifies the name of the image to be pushed. If you choose to set this property, then specify the same name that you specified while running the internal/docker-build step. However, if you omit this property, then the currently running pipeline container is committed and pushed.

You can use the following properties irrespective of whether the image-name property is specified or not: - username: Specifies the user name that is used to authinticate the registry. - password: Specifies the password that is used to authinticate the registry. - email: Specifies the e-mail address that is used to authinticate the registry. - repository: Specifies the name of the repository. If you are using a repository other than Docker Hub, prefix the value with the hostname of the private repository. - tag: A space- or comma-separated list of Docker tags that are applied to the built container. Wercker automatically applies a tag with the build number, and if a tag is left blank, Wercker uses the docker default of latest. - registry: Specifies the end point of the registry. Leave this property empty if you’re pushing the image to Docker hub. However, if you’re pushing the image to other registries, then begin the registry name with https://, and make sure that it has the same prefix as that of the repository. Append /v2 to the URL to push to registries that support V2 of the registry API.

The following properties are available only when you create an image from the current pipeline container. These should not be specified if the image is created from a Dockerfile using an internal/docker-build step - as they modify the image.

  • ports: Specifies the comma-separated list of ports that are exposed. The port number can end with the /tcp or the /udp protocols. If you do not specify a protocol, then /tcp is used. This property is equivalent to the EXPOSE instruction in a Dockerfile.
  • volumes: Specifies the comma-separated list of volumes that are exposed. This property is equivalent to the VOLUME instruction in a Dockerfile.
  • working-dir: Used to override the working directory of the container. This property is equivalent to the `WORKDIR instruction in a Dockerfile.
  • author: Used to set the author of the container. This property is equivalent to the MAINTAINER instruction in a Dockerfile.
  • cmd: Used to set the cmd for the new container. This is equivalent of the CMD instruction in a Dockerfile. Wercker only supports a single string value, which is in turn converted to exec form using go-shlex.
  • entrypoint: Used to set the entry point for the new container. This is equivalent of the ENTRYPOINT instruction in a Dockerfile. Wercker only supports a single string value, which is in turn converted to exec form using go-shlex.
  • disable-sync: Used to disable the synchronization of the environment variables before running the docker-push step. Set this property to true for the containers that do not support syncronization of the environment variables. This does mean that any of the exported environment variables will not be available for use in these properties.
  • message: Used to set a comment on a layer.
  • user: A string value used to specify a user inside a container.
  • env: A set of environment variables that you must set inside an image. Set the environment variables with one or more key-value pairs in the following format: VAR=value, with multiple values separated by spaces. Enclose the resulting string in double-quotes. If the value contains spaces, you must enclose it within single quotes. For example, "VAR1=value1 VAR2='Three word value'"
  • labels: A set of arbitrary key-value labels that you must set on an image. Set the labels with one or more key-value pairs in the following format: label=value, with multiple values separated by spaces. Enclose the resulting string in double-quotes. If the value contains spaces, you must enclose it within single quotes. For example, "Label1=value1" 'Three word key'=value2 Label3='Three word value'".
  • stopsignal: Specifies a signal to stop a container as a string or an unsigned integer. SIGTERM is the default value.

It is possible to use the environment variables inside all the properties, which are expanded. Environment variables that are exported during a build are also available, unless disable-sync is set to true.

Wercker supports pushing images to the following registries: