Separate building from running
Use multiple build stages when compilation needs tools that the running application does not. Keep build tooling out of the final image.
Keep the input small
Use .dockerignore to exclude unnecessary files. Copy dependency definitions before frequently changing source so useful build layers can be reused.
Plan for updates
Choose a trusted base image and rebuild regularly. Pinning a version improves reproducibility, but it also means you must manage updates deliberately.