In this guide we'll talk about some of the best practices to follow, when writing a Dockerfile.
Create a .dockerignore file in your source repository.
Create this file in the build context (the directory in which the command docker build is executed). This prevents from including files that are not necessary for building the Docker image resulting in a larger build context and larger image size) and reduces the time to build, pull and push the image, as well as the container runtime size.
This is an example:
*.md #excluded from build context
!README.md #included in build contextBy default, Docker uses the root user to run your processes. This has to be avoid if not strictly necessary. Add to the Dockerfile this instructions, before the ENTRYPOINT/CMD: RUN groupadd -r mygroup && useradd --no-log-init -r -s /bin/false -g aa myuser RUN chown -R myuser:mygroup <workdir> && chmod -R ug+rwx <workdir> ## or COPY [--chown=myuser:mygroup] <src> <workdir>
WORKDIR <workdir> USER myuser
There are some differences between ADD and COPY: COPY is preferred; use ADD only for local tar autoextraction (example: ADD archive.tar.gz /app). Differences between COPY and ADD: - COPY only supports the basic copying of local files into the container - ADD can also fetch file from remote URLs Don't do: ADD <http://example.com/big.tar.xz> /app/ RUN tar -xJf /app/big.tar.xz -C /app && rm /app/big.tar.xz RUN make -C /app all
But: RUN mkdir -p /app && \ curl -SL <http://example.com/big.tar.xz> | tar -xJC /app && rm /app/big.tar.xz && \ make -C /app all Using curl or wget instead of ADD, you can delete the files no longer needed after they’ve been extracted and you don’t have to add another layer in your image. There are some differences between ENTRYPOINT and CMD. ENTRYPOINT specifies a command that will always be executed when the container starts. CMD specifies arguments that will be fed to the ENTRYPOINT, and it will be overridden when running the container with alternative arguments. For example, if your Dockerfile is: FROM debian:wheezy ENTRYPOINT ["/bin/ping"] CMD ["localhost"]
Running the image without any argument will ping localhost: $ docker run -it test-image PING localhost (127.0.0.1): 48 data bytes 56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms 56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms ... Now, running the image with an argument will ping the argument: $ docker run -it test-image google.com PING google.com (173.194.45.70): 48 data bytes 56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms 56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms ...
For comparison, if your Dockerfile is: FROM debian:wheezy CMD ["/bin/ping", "localhost"]
Running the image without any argument will ping localhost: $ docker run -it test-image PING localhost (127.0.0.1): 48 data bytes 56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms 56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms ... But running the image with an argument will run the argument: docker run -it test-image bash root@e8bb7249b843:/#
Source code should not be included inside Docker images, but only the artifacts (if it is possible).
For example, if you have to dockerize a maven project, i don't have to copy all the project sources into the image (and so build inside the image), but only the .jar Don't do: FROM maven:3.5-jdk-8 AS build COPY src /app/src COPY pom.xml /app RUN mvn -f /app/pom.xml clean package //produces /app/target/demo.jar FROM java:8 AS run ... ENTRYPOINT ["java","-jar","/app/target/app.jar"] Instead of this, do the build before the docker build step and do this in your Dockerfile: FROM java:8 ... ADD /target/app.jar /app/app.jar ENTRYPOINT ["java","-jar","/app/app.jar"]
No comments:
Post a Comment