Introduction
This guide will help you build a Docker container for the Moonshine-dev application, which is written in Haxe with a Gradle REST API. The container will consist of three layers:
- Base Layer: A Debian 12-based image prepared using Packer and Ansible, as referenced here: Building a Template Image using Packer and Ansible
- Intermediate Layer: Common provisioning steps to speed up future builds.
moonshine-dev/base-latest - Application Layer: Installation and configuration of the Moonshine-dev application.
moonshine-dev/latest
See more here about Image Layers in Docker
Prerequisites
Ensure you have the following software and requirements met:
- Super.Human.Installer (SHI) Instance: Use a SHI instance, which is a GUI wrapper around Vagrant. This instance is based on a STARTcloud template and already has Ansible installed.
- Docker: Install Docker on the SHI instance. You can follow the official Docker installation guide for your operating system. or add the role startcloud.startcloud_roles.docker
Step 1: Clone the Repository
- Open a terminal in your SHI instance.
- Navigate to the directory where you want to clone the repository.
- Run the following command to clone the repository with submodules:
git clone --recursive https://github.com/STARTcloud/vagrant_box_template_creator
- Change into the cloned repository directory:
cd vagrant_box_template_creator
Step 2: Build the Base Layer
The base layer is a Debian 12-based image that serves as a foundation for other applications. It is built using Packer and Ansible.
Base Playbook
The base playbook for all STARTcloud images is as follows, this was referenced in the other article: Building a Template image with Packer and Ansible:
---
- name: "This Playbook Creates the Base Template via Ansible-Local"
become: true
gather_facts: true
hosts: all
collections:
- startcloud.startcloud_roles
roles:
- role: startcloud.startcloud_roles.dependencies
- role: startcloud.startcloud_roles.serial
- role: startcloud.startcloud_roles.cockpit
- role: startcloud.startcloud_roles.nfs
vars:
nfs_exports: []
nfs_rpcbind_enabled: true
nfs_rpcbind_state: started
- role: startcloud.startcloud_roles.ntp
vars:
ntp_area: ""
ntp_cron_handler_enabled: false
ntp_enabled: true
ntp_manage_config: false
ntp_restrict:
- "127.0.0.1"
- "::1"
ntp_servers:
- "ntp1.prominic.net iburst"
- "ntp2.prominic.net iburst"
ntp_timezone: America/Chicago
ntp_tinker_panic: false
- role: startcloud.startcloud_roles.motd
vars:
add_footer: false
add_update: true
remove_default_config: true
restore_default_config: false
sysadmins_email: [email protected]
sysadmins_signature: "STARTCloud Contact Email"
- role: startcloud.startcloud_roles.cleanup
Build the Base Image
Run the following command to build the base image:
packer build -var-file='definitions/cloud-credentials.json' -var-file='definitions/vendor.json' -var-file='definitions/templates/x64/debian12-server.json' tasks/build-ansible-local.json
This command uses the build-ansible-local.json
file to create a VirtualBox VDI file, which is then converted to a Docker image and pushed to both Vagrant Cloud and Docker Hub.
Step 3: Build the Intermediate Layer
The intermediate layer includes common provisioning steps to speed up future builds. It is built using the same Packer script (deploy.json
) as the application layer.
Intermediate Layer Playbook
The playbook for the intermediate layer is as follows:
---
- name: "Setup Intermediate Layer"
become: true
gather_facts: true
hosts: all
roles:
- name: startcloud.startcloud_roles.setup
- name: startcloud.startcloud_roles.hostname
- name: startcloud.startcloud_roles.dependencies
- name: startcloud.startcloud_roles.service_user
- name: startcloud.startcloud_roles.sdkman_install
- name: startcloud.startcloud_roles.sdkman_java
- name: startcloud.startcloud_roles.sdkman_gradle
- name: startcloud.startcloud_roles.ssl
- name: startcloud.startcloud_roles.supervisord
Build the Intermediate Layer
Run the following command to build the intermediate layer:
VERSION=0.0.1 sudo -E packer build -on-error=abort \
-var-file='definitions/cloud-credentials.json' \
-var-file='definitions/vendor.json' \
-var-file='definitions/templates/x64/debian12-server.json' \
-var "docker_hub_template_repo_name=debian12-server" \
-var "docker_hub_template_repo_tag=0.0.8" \
-var "playbook_file=provisioners/ansible/ansible_collections/moonshine/moonshine_roles/playbooks/main-base-playbook.yml" \
-var "repo_version=base-latest" \
-var 'repo_name=moonshine-dev' \
providers/docker/deploy.json
Step 4: Build the Application Layer
The application layer installs and configures the Moonshine-dev application. It uses the intermediate layer as its base.
Application Layer Playbook
The playbook for the application layer is as follows:
---
-
name: "Generating Playbook"
become: true
gather_facts: true
hosts: all
vars:
core_provisioner_version: 0.0.1
provisioner_name: PackerImageBuilder
provisioner_version: 0.0.1
settings:
hostname: app
domain: moonshine.dev
server_id: 500001
vagrant_user_pass: 'XaVuzq2vRV4fTk'
debug_all: true
selfsigned_enabled: true
haproxy_ssl_redirect: true
letsencrypt_enabled: false
service_user: java_user
service_group: java_group
service_home_dir: /local/notesjava
cert_dir: /secure
installer_dir: /vagrant/installers
completed_dir: /vagrant/completed
domino_organization: STARTcloud
domino_install_dir: /opt/hcl/domino/notes/latest/linux
collections:
- startcloud.startcloud_roles
- startcloud.hcl_roles
- moonshine.moonshine_roles
roles:
- name: startcloud.hcl_roles.domino_vagrant_rest_api
- name: startcloud.startcloud_roles.haxe
- name: moonshine.moonshine_roles.moonshinedev_deploy
- name: startcloud.startcloud_roles.haproxy
vars:
haproxy_cfg: /vagrant/ansible/ansible_collections/moonshine/moonshine_roles/roles/moonshinedev_deploy/templates/moonshinedev-haproxy.cfg.j2
Build the Application Layer
Run the following command to build the application layer, note that the repo_name and repo_version would be based off your intermediary image/layer above:
VERSION=0.0.1 sudo -E packer build -on-error=abort \
-var-file='definitions/cloud-credentials.json' \
-var-file='definitions/vendor.json' \
-var-file='definitions/templates/x64/debian12-server.json' \
-var "docker_hub_template_repo_name=moonshine-dev" \
-var "docker_hub_template_repo_tag=base-latest" \
-var "playbook_file=provisioners/ansible/ansible_collections/moonshine/moonshine_roles/playbooks/main-application-playbook.yml" \
-var "repo_version=latest" \
-var 'repo_name=moonshine-dev' \
providers/docker/deploy.json
Step 5: Testing the Image
After building the Docker image, you can test it by running the following command:
docker run -p 80:80/tcp -p 443:443/tcp -p 8080:8080/tcp -i -t startcloud/moonshinedev:latest /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
or
docker run -p 80:80/tcp -p 443:443/tcp -p 8080:8080/tcp -i -t startcloud/moonshinedev:latest
This command will start the Moonshine-dev application in a Docker container, allowing you to test its functionality.
If you need to debug the docker container, you can access it with the following commands
1. list the docker container and grab its name or id:
sudo docker container ls
2. The you can use exec to access the container:
sudo docker container exec -it <CONTAINER_ID_OR_NAME> /bin/bash
Conclusion
By following this guide, you have successfully built a multi-layer Docker container for the Moonshine-dev application. Each layer serves a specific purpose, from providing a base Debian 12 image to installing and configuring the application itself. This modular approach allows for efficient and flexible image management, making it easier to update and maintain the application over time.