Deploying Your First Docker Image on AWS
Preparing a Docker Image
Let’s start with creating and publishing a Docker image that we can then deploy to AWS. If you want to skip this part, you can just use the Docker image reflectoring/aws-hello-world:latest, which is available here : hub.docker.com/r/reflectoring/aws-hello-world
Creating the Docker Image
For this tutorial, we’ll create a simple Docker image from a Hello World application I created. You can pull it from GitHub to build the Docker image yourself.
The example application is a simple Hello World application that prints “Hello World” when you open the “/hello” endpoint in a browser.
To build a Docker image, the application has a Dockerfile:
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 8080
This is a Docker file wrapping our Spring Boot application. It starts with an OpenJDK on top of a Linux alpine distribution and takes the path to a JAR file as an argument. It then copies this JAR file into app.jar within its own filesystem and runs java -jar app.jar to start the application. Finally, we’re telling Docker that the application exposes port 8080, which is for documentation purposes more than for real effect.
Next, we have to build the Java application with ./gradlew clean build. This will create the file build/libs/aws-hello-world-0.0.1-SNAPSHOT.jar, which Docker picks up by default because we specified build/libs/*.jar as the default value for the JAR_FILE argument in our Docker file.
Now, we can build the Docker image. From the folder containing the Dockerfile, we run:
docker build -t reflectoring/aws-hello-world:latest .
To check if everything worked out, we can run
docker images | grep aws-hello-world
which will display all Docker images available locally that contain aws-hello-world in their name.
Testing the Docker Image
Let’s check if the Docker image we just built actually works. We start the image up with docker run:
docker run -p 8081:8080 reflectoring/aws-hello-world:latest
With -p we define that whatever is available on port 8080 within the container, Docker will make available via the port 8081 on the host computer. In other words, requests to port 8081 on the host computer (the host port) will be forwarded to port 8080 within the container (the container port).
Without specifying these ports, Docker won’t expose a port on which we can access the application.
When the Docker container has successfully started up, we should see log output similar to this:
... Tomcat started on port(s) 8080 (http) with context path ''
... Started AwsHelloWorldApplication in 3.222 seconds ...
Once we see this output, we can type localhost:8081/hello into a browser and should be rewarded with a “Hello World” message.
Publishing the Docker Image
To deploy a Docker image to AWS, it needs to be available in a Docker registry so that AWS can download it from there. So, let’s publish our image.
We can choose to publish our Docker image in any Docker registry we want, even our own, as long as AWS can reach it from the internet. We’ll publish it to Docker Hub, which is Docker’s official registry.
For business-critical applications that we don’t want to share with the world, we should have our own private Docker registry, but for this tutorial, we’ll just share the Docker image publicly.
First, we need to log in with Docker:
docker login registry-1.docker.io
We’re prompted to enter the credentials to our Docker Hub account.
We can leave out the registry-1.docker.io part because Docker will use this as a default. If we want to publish to a different registry, we need to replace this address.
Next, we push the Docker image to the registry:
docker push reflectoring/aws-hello-world:latest