Docker for Frontend Devs: Custom Docker Images for Development

When a layer changes, any cached layers on top of it are invalidated and will be rebuilt.

Therefore, if there is no change to our package.

json or the package-lock.

json then our entire image is cacheable and doesn't need to be rebuilt!PriorityThis is also why you want to have other Dockerfile commands that change less frequently near the top of our file.

As soon as one layer of our cache is invalidated, for example, if you change ENV PORT=8080 to another port, that cached layer and every cached layer after it is invalidated and Docker will have to rebuild those layers.

Building the Custom Docker ImageNow, build the image with this command: docker build –tag docker_demo:latest –file Dockerfile.

dev .

Using in the docker build command allows us to easily reference this image from our docker run commandThe .

at the end of the docker build command references the context where our custom Dockerfile can be found.

So, this command should be run from the root of our project directoryYou can run it with docker run docker_demo:latest, but unfortunately, we have more work to do to get it working quickly and easily from the command line.

Running our Container: Quality of Life ImprovementsWe’re going to be executing our docker run command daily, if not more frequently.

However, if we simply execute the docker run docker_demo:latest command, Docker will create a new container each time.

Docker won't stop the old container unless you do so explicitly.

This is very useful in many cases, but since we've hardcoded the host port, we'll run into port collisions on our host machine.

In order for us to easily stop and remove our old containers, we should name them so we can easily refer to them later.

Additionally, I want the running container to be removed if I cancel the running process.

docker run –rm -it –name docker_demo_container docker_demo:latestWhat was added?We added a –name field to the end of our run command.

This allows us to reference the container without looking up the hash.

Now, we can easily stop our container by name.

We also added the –rm and -it flags to our docker run command.

The –rm flag tells Docker to remove the container if and when it is stopped.

The -it flag keeps the terminal live and interactive once the container is started.

Mounting Host DirectoriesLet’s go back to our docker run command and let's find a way to mount our workspace directory to a folder within our container.

We can do this by adding a mount point to our container in the docker run command.

This will tell Docker that we want to create an active link between our host machine's folder ( src) and the Docker container folder ( dst).

Our new command should look like this:docker run –rm -it –name docker_demo_container –mount type=bind,src=`pwd`,dst=/usr/src/app docker_demo:latestBut this could conflict with our host machine’s node_modules folder since we're mounting our entire pwd to our app's location in the image (in case one of our developers accidentally runs npm install on their host machine).

So, let's add a volume to ensure we preserve the node_modules that exists within our container.

docker run –rm -it –name docker_demo_container –mount type=bind,src=`pwd`,dst=/usr/src/app –volume /usr/src/app/node_modules docker_demo:latestAccessing Ports Inside the ContainerIf you tried the above command (and you’re running a VueJS app), you should see:App running at: – Local: http://localhost:8080/ It seems you are running Vue CLI inside a container.

Access the dev server via http://localhost:<your container's external mapped port>/Docker is giving you a hint that we need to expose a port from our container and publish it on our host machine.

We do this by adding the –publish flag to our run command.

(We already have the EXPOSE command in our Dockerfile.

dev)tells Docker that traffic to the host machine (i.

e.

via localhost) on port <host-port> should be directed towards the container at the <container-port> that you define.

docker run in One CommandLet’s take a look at our final run command:docker run –rm -it –name docker_demo_container –publish 4200:8080 –mount type=bind,src=`pwd`,dst=/usr/src/app –volume /usr/src/app/node_modules docker_demo:latestRunning the above command will finally allow us to access our app via http://localhost:4200.

Testing it outLet’s build a fresh copy and run it.

If you try changing one of our file’s templates, you’ll see everything is still functioning as it should be.

But speaking of testing, what about unit tests?.Well, once our container is running, we can open a new terminal and docker exec a command to run in our container.

docker exec -it docker_demo_container npm run test:unitThe above command will create an interactive terminal connection with our container docker_demo_container and execute the command npm run test:unit in it, allowing us to run unit tests for our app.

In ClosingWe now have a way to build our development images and run them locally while maintaining the conveniences of Hot Module Replacement to keep our development workflow efficient.

Our developers don’t need to worry about dependencies on their host machine colliding with those in the image.

No more “but it works on my machine” excuses.

And, we also have a command we can easily run to execute our unit tests.

.

. More details

Leave a Reply