Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.
docker-compose buildcommands will create a temporary Docker container based on the previous image (specified in the
FROMdirective below) and then translate all of the other directives in the Dockerfile into configuration for the container or else commands to run inside the container. Every individual Dockerfile command creates a new image layer, and Docker will always rebuild the fewest layers possible when it can re-use "higher" layers -- that is, if you take a Dockerfile with 10 directives, build it, and then add an 11th directive to copy a file from the host onto the image, when you build it again it will only execute the 11th directive; the previous 10 layers haven't changed.
docker.io/ortussolutions/commandbox. ortussolutions is the account name and commandbox is the image name. docker.io is Docker Hub, and Docker will always use that address unless you specify a fully-qualified domain name for a different container registry (e.g.
FROMdirective that points to the image "beneath" it in the stack. This is one reason Docker images are so powerful: it's trivial to build on stable, well-established, "official" images; you may need to customize a few things here or there, but you don't need to re-invent the wheel.
mysql:8.0. If no tag is specified, Docker will use the tag
docker inspect. You can use any label, or you can conform to the Label Schema Convention. Or you can ignore Labels entirely.
ARGis similar to
ENVthat we'll see in a moment: it sets an environment variable inside the container, in this case telling Ubuntu that the console is being run by an automated tool and to ignore some warning output it might otherwise show us. Unlike
ARGenvironment variables are only set during the build process, while
ENVsets environment variables anytime a container based on this image is created. This particular
ARGis not necessary, but it makes the output of the rest of the build process a little cleaner.
apt-get update(since Docker images usually clean out
aptarchives before they finish, as ours will, too);
apt-get install -y nanowill install the nano text editor without prompting us to confirm; and
rm -rf /var/lib/apt/lists/*will delete the
aptarchives we downloaded with
apt-get update. The resulting layer will have all of those changes processed as a single layer, such that the only difference between this layer and the previous one is that
nanohas been installed.
.WARfile. If you're running Lucee, much of the available functionlaity has been moved out of the WAR file and into Lucee Extensions. While we could add individual
.lexfiles to a /deploy folder in our Docker Build process, that folder only exists after the engine itself has been warmed up; far better to tell Lucee what extensions we want during the warm-up process. As of April 2019, the easiest (if not the friendliest) means of doing so is to specify the unique ID, name, and version number of each extension in the
LUCEE_EXTENSIONSenvironment variable as follows:
ENV LUCEE_EXTENSIONS "UUID;name=My Extension;version=1.2.0,UUIDForExtension2;name=My Second Extension;version=1.1.0"
CFENGINEtells Commandbox which CF engine we want to deploy. It can be a Forgebox stub (as the example above is) or a URL or filesystem location resolving to a WAR file. See other examples in the comments in the Dockerfile!
CFENGINEdownloaded and installed, and then to start it up and install the extensions we've defined in
LUCEE_EXTENSIONS. This process will usually take at least a couple of minutes, and when it's done, the resulting image will be quite a bit bigger than the Ortus "base" image but it will start up in seconds rather than minutes.
inleaguewith it below to get an image tag of
ortussolutions/commandbox. To build it, we'll run
docker buildwith the
-toption to specify the image tag we want; without it, the image would be built and assigned an alphanumeric ID, but we could only refer to it by that ID. From the top level of the repository directory:
.in the above command tells Docker to use the current directory as the build content, so it will look for a
Dockerfilein that directory.
docker pull mydockerhubusername/cfswarm-commandboxor else
FROM mydockerhubusername/cfswarm-commandboxin a Dockerfile.
docker-compose buildto the rescue! Have a look at
docker-compose.ymlin the repository you cloned:
docker-compose buildin the root repository directory will run exactly the same
docker buildcommand that we ran before. The image tag is pulled from the
imagedirective in our YAML file, and the
.(context) from the
:alpinetag of the same image using
docker buildand specify an alternate Dockerfile:
docker-composelets us specify
ENVs, and all kinds of other options without changing our Dockerfile.