Login to Docker Hub with your credentials:
docker login
Tag your image with your Docker account id:
docker tag imagename dockeraccountid/imagename
Push to Docker Hub:
docker push dockeraccountid:imagename

Articles, notes and random thoughts on Software Development and Technology
Login to Docker Hub with your credentials:
docker login
Tag your image with your Docker account id:
docker tag imagename dockeraccountid/imagename
Push to Docker Hub:
docker push dockeraccountid:imagename
Several months back I spent some time playing with Kubernetes but it’s been a while so I need to retrace my steps to get back up to speed.
I’ve already have my Docker for Mac single Kubernetes node running (see here)
Next, I need to run a local Docker repository where I can push my Docker images for testing. I walked through these steps here.
I have a Docker image called examplespringboot that I want to deploy to my local single node Kubernetes cluster, so first up, tag it:
docker tag examplespringboot [ip of your docker machine]:5000/examplespringboot
And then push it:
docker push [ip of your docker machine]:5000/examplespringboot
With my local Kubernetes cluster up:
$ kubectl cluster-info
Kubernetes master is running at https://localhost:6443
KubeDNS is running at https://localhost:6443/api/v1/namespaces/kube-system/services/kube-dns/proxy
I created a deployment.yml for my Docker container using the example here:
apiVersion: apps/v1
kind: Deployment
metadata:
name: exampleservice
labels:
app: exampleservice
spec:
replicas: 1
selector:
matchLabels:
app: exampleservice
template:
metadata:
labels:
app: exampleservice
spec:
containers:
- name: exampleservice
image: 192.168.0.126:5000/examplespringboot
ports:
- containerPort: 8080
This references the Docker image from my local Docker repo.
To create the deployment:
$ kubectl create -f exampleservice-deployment.yml
Now you can describe the pod and the deployment and watch them come up:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
exampleservice-7b9b4b7db9-c7hx6 1/1 Running 0 9m
At this point the running pod is not exposed outside of the cluster. Following the steps here to expose as a service and assign an external ip:
$ kubectl expose deployment exampleservice --type=LoadBalancer --name=exampleservice
If you describe the service you now see it has a LoadBalancer Ingress assigned on localhost:
$ kubectl describe service exampleservice
Name: exampleservice
Namespace: default
Labels: app=exampleservice
Annotations:
Selector: app=exampleservice
Type: LoadBalancer
IP: 10.98.115.137
LoadBalancer Ingress: localhost
Port: 8080/TCP
TargetPort: 8080/TCP
NodePort: 30718/TCP
Endpoints: 10.1.0.16:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:
Calling localhost:8080/example/hello on my service, now it’s up and responding:
{"message":"hello!"}
Done!
Docker for Mac includes a single node kubernetes install that you can enable via the Docker Properties dialog:

Using kubectl you can take a look at what contexts you have configured, at some point I was playing with minikube, so now I have two:
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-for-desktop docker-for-desktop-cluster docker-for-desktop
minikube minikube minikube
To switch to the Docker for Mac cluster:
$ kubectl config use-context docker-for-desktop
Switched to context "docker-for-desktop".
Check cluster info:
$ kubectl cluster-info
Kubernetes master is running at https://localhost:6443
KubeDNS is running at https://localhost:6443/api/v1/namespaces/kube-system/services/kube-dns/proxy
Check running nodes:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
docker-for-desktop Ready master 11m v1.10.3
Now to deploy some containers!
(For a summary of kubectl commands, I have a summary post here).
Atlassian Confluence is already available as a Docker Image from the Docker Hub but you still need to provide a database instance for a production setup. Let’s build a docker-compose file to create a container from this image together with a container running MySQL.
First, per the docs on the Docker Hub page, create an external folder /data/confluence that will get mounted as a volume by the Container.
This is my first version to get this working (keep reading for refining this to include a JDBC driver)
[code]
version: ‘3’
services:
confluence:
image: atlassian/confluence-server
restart: always
volumes:
– /data/confluence:/var/atlassian/application-data/confluence
ports:
– 8090:8090
– 8091:8091
confl-mysql:
build: ./mysql
restart: always
environment:
– MYSQL_RANDOM_ROOT_PASSWORD=yes
– MYSQL_DATABASE=confluence
– MYSQL_USER=confluence
– MYSQL_PASSWORD=your-password
[/code]
After hitting your-ip:8090 for the first time, you can pick the ‘My own database’ option:

To connect to a MySQL db you need to drop a MySQL JDBC driver into /opt/atlassian/confluence/confluence/WEB-INF/lib so at this point we’ve got a couple of options. We could either copy the JDBC driver into the container (but since containers are ephemeral we’d lose this change if we started a new container from the image), or take a step back and rebuild the image including the driver:

The right thing to do would be to rebuild a custom image including the driver. So let’s do that.
Download the MySQL Connector driver from here.
Let’s commit it into our project and add a new Dockerfile to build a modified version of the official Confluence image, which is simply just these two lines:
[code]
FROM atlassian/confluence-server
COPY mysql-connector-java-5.1.46.jar /opt/atlassian/confluence/confluence/WEB-INF/lib
[/code]
Update the docker-compose file to build this new image instead of using the provided one from Docker Hub. Replace:
[code]
image: atlassian/confluence-server
[/code]
with
[code]
build: ./confl-mysql
[/code]
(or your corresponding name of your custom image containing the above Dockerfile)
Now when we startup this container and hit the app, the JDBC driver was recognized and we’re on to the next config page for our database connection params:

Entering our credentials and pressing Test, we’ve got an error about the default encoding:

To address this, the Confluence setup docs here describe editing the my.cnf file in MySQL, or alternatively I could pass params. The MySQL docs have a chapter on configuring and running MySQL in Docker, and this Q&A on Stackoverflow describes passing the optional params in a command section in your docker-compose file.
My first attempt was to add this:
[code]
confl-mysql:
build: ./mysql
restart: always
command: character-set-server=utf8 collation-server=utf8_bin
[/code]
but the syntax was not quite right yet, resulting in the container startup in a restart loop, and this error appearing in the container logs:
/usr/local/bin/docker-entrypoint.sh: line 202: exec: character-set-server=utf8: not found
Reading docs for the command option, the command in the docker-compose file needs to be the command to start the app in the container as well as the optional params. So now I’m here:
[code]
confl-mysql:
build: ./mysql
restart: always
command: [mysqld, –character-set-server=utf8 –collation-server=utf8_bin]
[/code]
Now we’re getting closer. Logs from my MySQL container and how showing:
ERROR: mysqld failed while attempting to check config command was: "mysqld --character-set-server=utf8 --collation-server=utf8_bin --verbose --help" mysqld: Character set 'utf8 --collation-server=utf8_bin' is not a compiled character set and is not specified in the '/usr/share/mysql/charsets/Index.xml' file
Some Googling made me realize each of the params is command separated, so next update is:
[code]
confl-mysql:
build: ./mysql
restart: always
command: [mysqld, –character-set-server=utf8, –collation-server=utf8_bin]
[/code]
and now we’ve got both containers starting up. The list of params should be updated to add all the optional params listed in the Confluence MySQL set up docs, otherwise you’ll get an error for each missing param. The complete list is:
command: [mysqld, --character-set-server=utf8, --collation-server=utf8_bin, --default-storage-engine=INNODB, --max_allowed_packet=256M, --innodb_log_file_size=2GB, --transaction-isolation=READ-COMMITTED, --binlog_format=row]
… and my VM has run out of diskspace, so time to expand my disk. Back shortly.
Ok, back. Restarted and now we’re in business:

Complete config and now the containers are up!