1. Use a smaller base image: The base image is the foundation of your container. If you start with something large, your final image will also be large. Some programming languages like Ruby or Python are interpreted and require a runtime environment, thus it’s a good practice to search for the lightweight version of standard images like alpine images which are usually smaller than standard ones.
1. Reduce the number of layers: Each command you put in the Dockerfile creates a layer in your Docker image. You can effectively reduce number of layers by combining commands using `&&`.
1. Eliminate unnecessary cache files: Docker images store cache data and it can be removed after package installation with appropriate package manager commands in most distributions.
1. Use multi-stage builds: Docker’s multi-stage builds are a great way to keep the size of the final image down. The idea is that you build everything in a larger build image and then copy just the pieces you need into a smaller runtime image.
1. Ignore unnecessary files: Use `.dockerignore` file to avoid copying unnecessary files to the image. It supports the same rules as `.gitignore` files.
1. Don’t include debuggers, build tools, or test data in your production images: Make sure these only get in your build images, and not in your runtime images.
1. Clean up after package installation: During software installation with package managers, they can create unwanted cache or extra files and it’s recommended to clean up them.
1. Using squash: Docker —squash is a tool to minimize layers into a single one, reducing the size while maintaining the usability of the container.
Remember that the techniques you use to reduce image size might vary depending on your needs and the nature of your application.