Contribute a Dockerfile
The following steps describe how you can create a Dockerfile for a malware analysis tool and contribute it to the REMnux collection of Docker images.
To get started, review:
The details below.
Before starting this work, consider reaching out to Lenny Zeltser to confirm that it makes sense to include the tool as part of the REMnux collection of Docker images.
1. Install Git and Docker
Follow the steps appropriate for your operating system to install Git and Docker on your system.
Clone the REMnux/docker repository, which contains the existing Dockerfiles:
git clone https://github.com/REMnux/docker.gitBrowse the existing Dockerfiles in the repository to see how other tools are packaged. Instead of creating a file from scratch, consider using an existing Dockerfile as a starting point for your own.
2. Create the Dockerfile
Create a subdirectory named after your tool in the local copy of the repository, and add a Dockerfile inside it. A REMnux Dockerfile follows a consistent structure. The sections below explain each part, using the radare2 Dockerfile as the primary example.
Header Comments
Begin the file with comments that state the tool's name, website, description, author, license, and usage instructions:
Base Image and Labels
Use a FROM directive to specify the base image, followed by LABEL directives for maintainer information and the date of the last update:
New Dockerfiles should use a current Ubuntu LTS base image such as ubuntu:24.04. Some existing images in the repository use older versions.
Locale Settings
Set the locale environment variables so that tools don't encounter encoding issues:
Build Arguments
Use ARG to define version numbers as build-time variables. This makes it easy to update the tool version later without changing multiple lines:
Package Installation
Install the Ubuntu packages your tool requires using apt-get. Chain commands with && and clean up the package cache in the same RUN layer to minimize the image size. The \ character breaks the package list across multiple lines for readability. Assume that a given package is absent unless you explicitly install it, since the base image is a minimal Ubuntu installation:
Non-Root User Creation
Create a non-root user so that the tool runs with restricted privileges. The following block creates the user, sets up a home directory and working directory, and grants passwordless sudo access:
Application Installation
The installation steps vary by tool. The radare2 Dockerfile downloads a .deb package from a GitHub release and installs it using apt-get, which also resolves any dependencies the package requires. The ARG variable defined earlier keeps the version number in one place:
Final Directives
The closing directives switch to the non-root user, run any user-level initialization the tool requires, set environment variables and the working directory, declare a volume for file sharing, expose network ports, and specify the default command:
CMD specifies a default command that can be overridden when the user launches the container. ENTRYPOINT specifies a command that always runs, with any arguments passed at launch appended to it. For example, the thug Dockerfile uses ENTRYPOINT ["thug"] so users can pass URLs directly: docker run --rm remnux/thug http://example.com. Most REMnux images use CMD ["/bin/bash"] to provide an interactive shell by default.
Simple Python tools can use a python:3-slim base image instead of Ubuntu. For an example, see the binary-refinery Dockerfile, which installs the tool using pip directly.
3. Build and Test the Image
It's difficult to create a working Dockerfile in one step. When developing your Dockerfile, consider launching a base container interactively to figure out the installation commands:
Manually type and test each installation command inside the container's shell. Once you've validated that a specific sequence of commands works, transcribe them into your Dockerfile.
This prototyping workflow saves time: launch the base container, figure out the steps interactively, then write them into the Dockerfile one or two directives at a time.
Once your Dockerfile is ready, go to the directory where it resides and build the image, replacing "image-name" with the name you'd like to assign:
After Docker builds the image, run it to verify that the tool works:
Test the following inside the container:
The tool runs and produces expected output.
The non-root user is active (check with
whoami).Volume mounting works: run with
-v ~/workdir:/home/nonroot/workdirand verify files are accessible.
4. Handle File and Network Interactions
The container is isolated from the host system: by default it can communicate over the network in the outbound direction, but won't accept inbound traffic. If the container is invoked with the --rm parameter, its contents disappear after it stops running. When building the image, anticipate the user's need to communicate with the application inside the container over the network or to pass files in and out of the container.
Accessing Network Ports in the Container
If the tool listens on a network port, the user must explicitly expose it when launching the container using the -p parameter. For example, radare2 includes r2agent, which provides a web interface on port 8080. To access this from outside the container, the user specifies -p 8080:8080:
This maps the container's port 8080 to the underlying host's port 8080, allowing the user to connect by browsing to http://localhost:8080. Use the EXPOSE directive in the Dockerfile to document which ports the application uses, and include the -p flag in the usage instructions in the header comments.
Sharing Files with the Container
Some tools expect the user to provide input or retrieve output via the file system. Docker supports the -v parameter to share a directory between the underlying host and the container. For example, to share a working directory with the radare2 container:
This maps the local ~/workdir directory to /home/nonroot/workdir inside the container. Use the VOLUME directive in the Dockerfile to declare the expected mount point. To ensure the non-root user inside the container has access to the shared directory, the user may need to make it world-accessible (chmod a+xwr ~/workdir) before launching the container.
5. Create a Pull Request
Once you have a working, tested Dockerfile in the local copy of the REMnux/docker repository, create a GitHub pull request for that repo, so your Dockerfile may be considered for inclusion in the REMnux collection. Your pull request should include a directory named after the tool, containing the Dockerfile.
If the pull request isn't working, consider submitting the file to Lenny Zeltser by email.
After accepting the pull request, the REMnux maintainer handles building and publishing the Docker image to Docker Hub. You don't need to push the image yourself.
Last updated