visit
Aptible is a No Infrastructure Platform that offers robust solutions for simplifying and enhancing the security and compliance aspects of software applications. Aptible streamlines the complex process of achieving and maintaining industry-standard certifications such as HIPAA, SOC 2, and GDPR.
Sounds interesting, isn’t it? Like many of you I love to try new things. Aptible gives one month of a free trial which is just perfect to poke around.
Let’s assume you have an existing app hosted somewhere (in my case it’s DigitalOcean) and you really want to try out Aptible. I took almost-one-line-spring-boot-app from my previous article about Release Driver Development. There we had a decent yet simple CI/CD pipeline based on Github Action. So let’s go ahead and make it work with Aptible.
APTIBLE_USERNAME
and APTIBLE_PASSWORD
variables accordinglyCreate App
button). The same as DigitialOcean, Aptible doesn’t automatically create an app on the first run.To be able to deploy to Aptible we need to add a new step to our existing Github Actions pipeline. I don’t want to get rid of DigitalOcean step, so let’s add a switcher to the env
section together with Aptible-related params:
env:
# Where to deploy. Options are 'digitalocean' or 'aptible'
DEPLOY_TARGET: 'aptible'
# Aptible deploy params
APTIBLE_ENVIRONMENT: 'google-aeb'
APTIBLE_APP: 'deployinator'
- name: Deploy to Aptible
if: ${{ env.DEPLOY_TARGET == 'aptible' }}
uses: aptible/aptible-deploy-action@v1
with:
username: ${{ secrets.APTIBLE_USERNAME }}
password: ${{ secrets.APTIBLE_PASSWORD }}
environment: ${{ env.APTIBLE_ENVIRONMENT }}
app: ${{ env.APTIBLE_APP }}
docker_img: ${{ secrets.DOCKERHUB_USERNAME }}/deployinator:${{env.RELEASE_VERSION}}
If endpoint provisioning fails, restart your app using the aptible restart command. You will see a prompt asking you to do so.Note this failure is most likely due to an app health check failure. We have troubleshooting instructions here: My deploy failed with HTTP health checks failed
The only way to check what exactly has happened is to install Aptible CLI and restart the app.
> brew install --cask aptible
# be ready to provide login/password
> aptible login
> aptible restart --app deployinator
...
ERROR -- : Your Docker image must EXPOSE a port to provision an Endpoint, add an EXPOSE directive in your Dockerfile.
ERROR -- : FAILED: Wait up to 180s for containers in service cmd to respond to HTTP health checks
...
We have to add EXPOSE 80
to the Dockerfile to let Aptible know how to configure the endpoint and do the heath checks. We also need to change Spring Boot server’s port accordingly by adding server.port=80
to application.properties
file. You can take a look at the full code at branch.
That’s way better. The only thing our app can do is to show the version under /version
endpoint. So, copy the hostname from the endpoint and try it.
Perfect, it works.
Another option I mentioned in the beginning is to deploy by Git Push. To make it work you have to press the Deploy Code button on the Dashboard and go through a pretty straightforward which includes providing your public ssh key and adding Aptible’s Git repo as a remote for your existing repo. The idea here is by pushing into Aptible’s Git remote you trigger (re-)deployment. It’s completely fine to to work with your existing Git repo (named origin) as before, but when you need a deploy, just run something like:
git push aptible main
Think about:
gradlew build
because it’s the only thing between you and Aptible.
# Temp container to run gradle build
FROM gradle:latest AS BUILD
COPY --chown=gradle:gradle . .
USER gradle
# Tag current commit with commit's sha for versioning purposes
RUN git tag $(git rev-parse --short HEAD)
RUN gradle build
# Main stage
FROM eclipse-temurin:17
EXPOSE 80
COPY --from=BUILD /home/gradle/build/libs/deployinator-*.jar /app/deployinator.jar
ENTRYPOINT java -jar /app/deployinator.jar
We are using a multi-stage build. First phase is to build a jar file. To make it happen we start with temporary gradle:latest
image, copy all the files inside and run gradle build
. There is also one trick in here. As we copied all the source files, we also have .git
folder inside the image (it is temporary, no worries about extra files). The reasoning behind this is to let access Git tags and provide version info for Gradle.
docker build ...
.git
foldergit tag $(git rev-parse --short HEAD)
tags current commit with commit hashgradle build
gradle-git-plugin fetches last tag and makes it a project versiondocker run ...
and exposes our app to the world on a port defined in the EXPOSE
statement.
Commit hash is not the best option for a project’s version. SemVer or simply buildNumber + gitHash is slightly better (a bit more info about it in a previous article).
However, I couldn’t find a way to access anything similar to buildNumber.APTIBLE_PROCESS_INDEX
as --build-arg
to docker build command.aptible.env
is not accessible from the container’s root
# Check current hash
> git rev-parse --short HEAD
703496a
# Kick-off deployment
> git push aptible deploy-aptible-on-git-push:main