Build docker containers with Leiningen, no docker installation needed. Uses Google's Jib toolkit.
Note! This is alpha quality code and has not been thoroughly tested. Use at your own discretion (and create a PR if you improve something)
Clojure 1.10.0 or later is needed. Leiningen 2.9.0 or later is needed. This will probably work with Java 8 but I've only tested with Java 11.
Your project must emit an uberjar or something closely like it for this plugin to be useful in its current state.
Configure your project.clj as follows:
:plugins [[vaik.io/lein-jib-build "0.2.0"]]
:jib-build/build-config {:base-image {:type :registry
:image-name "gcr.io/distroless/java"}
:target-image {:type :docker
:image-name "helloworld"}}
Build the image and deploy it to the specified registry:
$ lein do uberjar, jib-build
Build the image and deploy it to the specified registry:
$ docker run helloworld
Hello, world!
There's also an example project
The jib-build/build-config
map supports the following required options:
:base-image {...}
- base Docker image to build upon, see below for details:target-image {...}
- what to do with the built image, also see belowThe following are optional:
:entrypoint [...]
- a vector of strings to use as the container's ENTRYPOINT value, defaults to ["java" "-jar"]
:arguments "..."
- a string to give to the entrypoint as arguments, defaults to the name of the project's uberjarThese options are usable with both base-image
and target-image
.
;; Deploy to your local docker daemon (requires dockerd to be running)
:target-image {:type docker
:image-name "helloworld"}
;; Deploy as a tar archive
:target-image {:type tar
:image-name "target/helloworld.tar"}
;; Deploy to a Docker registry with optional username/password authentication (please mind your security).
:target-image {:type registry
:image-name "docker.io/foobar/helloworld"
:username "username" ;; optional
:password "password" ;; optional
}
If you're using AWS ECR there's direct support for more sophisticated authentication.
Deploy to ECR with assume-role (this is the recommended option):
:target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn leiningen.aws-ecr-auth/ecr-auth
:args {:type :assume-role
:role-arn "arn:aws:iam::123456789:role/nazgul"}}}
Deploy to ECR using a profile:
:target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn leiningen.aws-ecr-auth/ecr-auth
:args {:type :profile
:profile-name "nazgul"}}}
Using environment variables:
AWS_ACCESS_KEY_ID
(required)AWS_SECRET_ACCESS_KEY
(required)AWS_SESSION_TOKEN
(optional):target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn leiningen.aws-ecr-auth/ecr-auth
:args {:type :environment}}}
With an access key:
:target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn leiningen.aws-ecr-auth/ecr-auth
:args {:type :access-key
:access-key-id "AK1231232414"
:secret-access-key "111111111111111"}}}
With JVM system properties:
aws.accessKeyId
(required)aws.secretKey
(required):target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn leiningen.aws-ecr-auth/ecr-auth
:args {:type :system-properties}}}
Create a function in a namespace accessible to leiningen with a single argument:
(defn custom-authorizer [config]
{:username (:username config)
:password (apply str (reverse (:encrypted-password config))})
The function gets passed the args
map:
:target-image {:type registry
:image-name "123456789.dkr.ecr.mordor-east-1.amazonaws.com/helloworld"
:authorizer {:fn my-namespace/my-custom-authorizer
:args {:username "Sauron" :encrypted-password "TERCESYREV"}}}
So that things would not be too easy, Leiningen includes some libraries that are a bit long in the tooth. And when creating plugins, those libraries override everything you bring with you.
The main culprit in this case is Guava, a current version of which is required by the jib-core
library used
by this plugin. Leiningen however provides an old version, so we need to shadow the Guava library inside jib-core
for it to function.
I have placed a forked version of jib
as a Git submodule, which contains the required shadowing configuration.
The included build.sh script does everything that's needed:
$ ./build.sh
--- Checking that we have the required submodule
--- Build the customised jib-core
BUILD SUCCESSFUL in 2s
4 actionable tasks: 2 executed, 2 up-to-date
'jib/jib-core/build/libs/jib-core-0.12.1-SNAPSHOT-GUAVASHADOW.jar' -> 'lib/jib-core-0.12.1-SNAPSHOT-GUAVASHADOW.jar'
--- Now build the plugin
Created /..../lein-jib-build/target/lein-jib-build-0.2.0.jar
Wrote /..../lein-jib-build/pom.xml
Installed jar and pom into local repo.
Another similar thing is that Leiningen includes an old version of clojure.data.xml
, which is slightly incompatible
with the cognitect/aws-api
library used for ECR authentication. There's an ugly with-redefs
somewhere because
of that.
Copyright 2019 Ville Vehviläinen
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Can you improve this documentation? These fine people already did:
vehvis, Ville Vehvil?inen & Ville VehviläinenEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close