Elevating IaC Workflows with Spacelift Stacks and Dependencies 🛠️

Register for the July 23 demo →

Docker

What is Docker Init & When to Use It – Best Practices

docker init

Docker is the most popular development platform for building and running containers. It’s redefined how software is built and deployed, but many teams still struggle with correctly configuring their projects for Docker support.

Fortunately, there’s now a solution available: modern Docker releases include the docker init command, a feature that lets you quickly add Docker to a project by creating a standard set of config files that are appropriate for your programming language. This saves time and increases consistency when you’re Dockerizing a new application.

We’ll explore docker init in this article by discussing when it’s useful and showing how to get started.

We’ll cover:

  1. What is Docker init?
  2. When to use Docker init?
  3. How to use Docker init – example
  4. Best practices for using Docker init

What is Docker init?

The docker init command is a utility that automates the process of enabling a project to be built and run with Docker. It allows you to hit the ground running, without having to first learn how to write Docker’s config files.

Before an app can be run in a Docker container, it must first be built into a Docker image. Images package your code and dependencies into portable units that define your container’s initial filesystem. Images are created from Dockerfiles that contain instructions listing the files to copy and commands to run in order to assemble the filesystem.

Dockerfiles can become quite complex, even for relatively simple apps. Your Dockerfile will typically need to include the following steps:

  1. Select or assemble an appropriate base image that provides your container’s OS and programming runtime—such as ubuntu:22.04 or node:20.
  2. Install any additional OS packages, programming languages, and frameworks your project requires.
  3. Fetch your project’s programming language dependencies (e.g., by using npm, Rust, or Gradle).
  4. Copy in your source code.
  5. Perform any filesystem or environment changes that are required by your app.

Docker init provides a set of Dockerfile templates that include these steps and other best practices with support for ASP.NET, Go, Node, Python, and Rust server applications (compatibility with Java and PHP apps is also planned). When you use Docker init, a ready-to-use Dockerfile and other resources are added to your project, allowing you to immediately build your image and start a container.

What files does Docker init create?

Running docker init currently adds three files to your project:

  • Dockerfile — This is the file that describes how to build your image’s filesystem. It includes the best practices and common requirements of the programming language you’re using.
  • compose.yaml — This is a Docker Compose configuration file that lets you start your app and its dependencies (such as database connections) as a stack of multiple independent containers.
  • .dockerignore — .dockerignore files are used to specifically exclude paths in your project that don’t need to be involved in image builds. They improve build performance by preventing wasteful copies of redundant content to the Docker daemon that performs the build. Docker init automatically excludes common paths, such as dependency folders, that will be automatically recreated when package manager install commands are run during your build.

These three files give you everything you need to containerize simple apps.

docker init vs docker-init

A potential source of confusion for docker init users is the command’s obvious similarity to docker-init, a standalone binary that’s used as the default init process for new containers.

docker init and docker-init are entirely separate tools. You can use docker init to scaffold your configuration in new Docker projects, while docker-init is a Docker-internal utility that you shouldn’t ever need to manually invoke.

When to use Docker init?

Docker Init is helpful in several real-world development scenarios:

  • Quickly bootstrap new projects: You can quickly bootstrap new apps and services by using docker init to create your Dockerfile and associated resources. This saves time and improves consistency across your project inventory.
  • Add Docker to existing projects, with sensible defaults: You can use Docker init to efficiently configure legacy projects for use with Docker, even when they’re written in varying programming languages. docker init will ensure appropriate settings are always used.
  • Learn how to use Docker with additional programming languages: Perhaps you’re already comfortable writing Dockerfiles for Python apps, but what if you’re now tasked with launching a Go service? Inspecting the output of docker init is a quick way to learn the basics of how to Dockerize apps written in any of the languages that the tool supports.
  • Save time and automate more project management tasks: Overall, docker init can save you time and reduce the amount of work involved with software project management. You might still need to alter the files it creates, but having a ready-to-run starting point is often preferable to assembling your Docker configuration from scratch each time.

Now let’s look at an example of how to use Docker init to containerize a simple application.

How to use Docker init - example

As mentioned above, Docker Init currently supports ASP.NET, Go, Node, Python, and Rust. There’s also an “Other” option that provides a generic starting point for other types of app—we’ll discuss this later on.

We’ll now use Docker Init to Dockerize a Node.js project. You’ll need to have Docker and Node.js already installed on your machine to follow along with this tutorial.

1. Install Docker init

Docker init is implemented as a Docker CLI plugin. It’s included with Docker Desktop versions v4.18 and later. Docker init isn’t currently included in Docker Engine, and there’s no supported manual installation method. Therefore, you must be using Docker Desktop in order to use the docker init command.

2. Create a minimal Node.js app

To begin, navigate to a new directory for the files you’ll create in this guide. Then, copy the following Node.js app and save it as main.js in your directory:

const express = require("express");

const app = express();

app.get("/", (req, res) => {
	res.send("Node.js demo app using Express.");
});

app.listen(3000, () => {
	console.log("App is listening.");
});

The app starts an Express web server on port 3000. It serves a single route (/) that sends a basic message in its response.

Run the following command to install the Express dependency in your project using npm:

$ npm install express

Now you’re ready to containerize your app.

3. Use Docker init to containerize your app

docker init is an interactive command that doesn’t require any flags. Instead, you’ll be prompted to answer a series of questions to configure your app.

First, run docker init within your working directory—you’ll see some initial help text, followed by a prompt to select the application platform you’re using:

$ docker init

Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with sensible defaults for your project:
  - .dockerignore
  - Dockerfile
  - compose.yaml

Let's get started!

? What application platform does your project use?  [Use arrows to move, type to filter]
> Node - (detected) suitable for a Node server application
  Go - suitable for a Go server application
  Python - suitable for a Python server application
  Rust - suitable for a Rust server application
  ASP.NET Core - suitable for an ASP.NET Core application
  Other - general purpose starting point for containerizing your application

You can see that the Node project type has been automatically detected for our sample app. Press the enter key to accept it.

Next, you’ll be asked which version of Node.js you’re using:

? What version of Node do you want to use? (18.16.0)

The default selection will match the Node.js version that’s detected on your machine—18.16.0 in this case. You can press enter to accept the default or type a new version number instead. If you specify a particular version, it must have a matching Docker image available on Docker Hub.

Next, you’ll be asked to identify the package manager you’re using—npm should be auto-detected so you can immediately press enter to continue:

? Which package manager do you want to use?  [Use arrows to move, type to filter]
> npm - (detected)
  yarn
  pnpm

The next prompt requires you to enter the command that will be used to run your app when containers start:

? What command do you want to use to start the app? [tab for suggestions]

For this tutorial, the sample code is saved as main.js so you should use node main.js as your command. This will run your application using the node binary found in the container and your main.js source code. The Docker Init-generated Dockerfile automatically copies your source into the container’s working directory.

Finally, you need to tell Docker what port your app is configured to listen on. This is 3000 in this tutorial.

? What port does your server listen on?

You should then see a confirmation that your three Docker config files have been created:

CREATED: .dockerignore
CREATED: Dockerfile
CREATED: compose.yaml

âś” Your Docker files are ready!

4. Run your app

Now that you’ve used Docker Init to containerize your project, you can go ahead and run your app with Docker.

It’s easiest to use Docker Compose to both build your image, then start a container in a single command:

$ docker compose up --build
[+] Building 50.1s (13/13)	FINISHED                        docker:default
(truncated)
[+] Running 2/2
 âś” Network spl-docker-init_default     Created             0.2s
 âś” Container spl-docker-init-server-1  Created             0.3s
Attaching to spl-docker-init-server-1
spl-docker-init-server-1  | App is listening.

You’ll see verbose logs in your terminal as Docker builds your image’s filesystem layers; it’ll then create your container and attach it to its foreground process so you can see your app’s logs.

Now you should be able to reach the app at localhost:3000:

$ curl http://localhost:3000
Node.js demo app using Express.

That’s it—you’ve successfully generated Docker config files, built your image, and run your app!

How to containerize other types of applications?

It’s best to use the language-specific template provided by docker init when possible. However, if your app’s not supported—or you’d prefer to have a less guided experience—you can select the “Other” template type at the first prompt.

Choosing “Other” will write minimal Dockerfile, compose.yaml, and .dockerignore files that are ready for you to customize. They’re a good way to familiarize yourself with Docker basics and best practices because the generated output is well-documented and includes tips, explanations, and optional capabilities you can enable by uncommenting sections of the files. For example, there’s a ready-to-use example of how to deploy a PostgreSQL database connection alongside your app available in the default compose.yaml.

Best practices for using Docker init

docker init is a relatively simple command, but there are still a few points to keep in mind when using it:

1. Provide accurate answers to the Docker init prompts

When you’re using one of the language-specific app templates, as in this tutorial, it’s important you supply correct answers to all the terminal prompts you’re displayed. Otherwise, the generated configuration might not be compatible with your project, and you’ll see errors when you try to build or run your image.

2. Analyze whether the default base image is suitable for your app

A suitable base image will be automatically selected for your project, based on the inputs you supply. However, this might need to be adjusted if the base image’s operating system or version doesn’t match your app’s requirements. For example, the Node.js template uses Alpine-based images, but your project could depend on a Debian environment. You can change the base image by modifying the FROM instruction that’s near the top of the generated Dockerfile.

3. Customize generated files after creation to match your use case

docker init provides a useful starting point but you may have to customize the generated files if your app has additional requirements, such as other containerized service dependencies that should be included in your Compose stack.

4. Be careful when using Docker init with existing projects

docker init can be used with existing projects—and is a quick way to make them Docker-compatible—but care should be taken if you’ve already made previous efforts to add Docker support. You’ll be warned if an existing file will be overwritten by the command’s output; in that case, it can be best to consult other team members to check whether the file is already updated and ready to use.

5. Ensure all team members understand what Docker init is doing

docker init is a good way to familiarize new team members with Docker, without making them learn the entire image authoring workflow. However, it’s important that everyone understands what the command is doing (outputting language-specific templates) and how it fits into the Docker ecosystem.

These points will ensure you can utilize Docker Init without encountering issues in the future.

Key points

In this article, we’ve looked at how Docker init lets you automate initial Docker configuration in your projects. It writes a Dockerfile, compose.yaml, and .dockerignore for you, lowering the learning curve and accelerating setup time. Note that while we’ve focused on using Docker Init with Node.js, the interactive prompt steps are similar for the other supported programming languages too.

Docker Init is a convenient tool but its output won’t always be suitable to use as-is. More advanced projects will still require customization of your Dockerfile, such as to install any extra dependencies you require, or to make changes to the base image that’s used. Similarly, you may have to modify your Docker Compose compose.yaml file to add any extra services that you require.

Looking for more help to master Docker? Check out the other content on the Spacelift blog, such as this Docker cheat sheet for Docker CLI commands.

We encourage you also to explore how Spacelift offers full flexibility when it comes to customizing your workflow. You have the possibility of bringing your own Docker image and using it as a runner to speed up the deployments that leverage third party tools. Spacelift’s official runner image can be found here.

The Most Flexible CI/CD Automation Tool

Spacelift is an alternative to using homegrown solutions on top of a generic CI. It helps overcome common state management issues and adds several must-have capabilities for infrastructure management.

Start free trial

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide