= Dockerfile = '''`Dockerfile(5)`''' is a declarative langauge for building a container image. Several container toolchains are capable of compiling Dockerfile files, including [[Docker|docker(1)]] and [[Podman|podman(1)]]. <> ---- == Example == {{{ # Setup FROM alpine:latest RUN apk update RUN apk add postgres14 # Data persistence VOLUME /var/lib/postgresql/data # Configuration COPY local/path/to/postgresql.conf /etc/postgresql/postgresql.conf # The containerized process USER postgres CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"] }}} ---- == Syntax == A Dockerfile consists of lines like `INSTRUCTION arguments`. Instructions are case-insensitive but, by convention, should be capitalized. Lines beginning with `#` are comments. A `#` anywhere else is treated as an argument. Except for parser directives and global scope `ARG` instructions, a Dockerfile '''must''' begin with a `FROM` instruction. Long lines can be split using `\`, as in: {{{ RUN echo hello \ world }}} Note that comments are stripped before lines are parsed, so the above is equivalent to: {{{ RUN echo hello \ # comment world }}} Whitespace is preserved for arguments, but ignored for instructions and comments. By convention, there should never be whitespace ahead of an instruction or comment. ---- == Instructions == === From === ---- === Label === The '''`LABEL`''' command is used for image metadata. {{{ LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines." }}} ---- === Arg and Env === ---- === Run and Shell === ==== Shell ==== The '''`SHELL`''' command overrides how `RUN` commands are handled. The default shell is `["/bin/sh", "-c"]` on [[Linux]] and `["cmd", "/S", "/C"]` on [[Windows]]. ---- === Add === ---- === Copy === To copy a single file, try: {{{ COPY index.html /usr/share/nginx/html/index.html # or COPY index.html /usr/share/nginx/html/ }}} '''If''' and '''''only if''''' the destination ends in `/`, it is interpreted as a directory. To copy multiple files, try: {{{ COPY README.md package.json __BUILD_NUMBER /destination/path/ # or COPY ["__init__.py", "__main__.py", "app.py", "/destination/path/"] # or COPY *.conf /destination/path/ }}} The destination must be a directory when copying multiple files. Note that `COPY` handles source directories differently. `COPY dir1 dir2 /destination/path/` is actually `COPY dir1/* dir2/* /destination/path/` ==== Ownership ==== Files and directories are copied with uid and gid of 0. To set ownership, try: {{{ COPY --chown=nginx:nginx index.html /usr/share/nginx/html/index.html }}} If a user name or group name is used, the container will depend on having `/etc/passwd` and `/etc/group` files. If this isn't feasible, consider using numeric uids and gids. ==== Copy from ==== `COPY` has a `--from=CONTAINER` option. In a multi-stage build, files and binaries are copied from a ''build'' container into the ''production'' container. This keeps the statically-compiled dependencies outside of the production image. {{{ FROM golang:latest AS builder WORKDIR /app COPY * ./ RUN go mod download RUN go build -o /my-binary-name FROM alpine:latest WORKDIR / COPY --from=builder /my-binary-name /my-binary-name EXPOSE 8080 ENTRYPOINT ["/my-binary-name"] }}} ==== Build Context ==== `COPY` depends on the build context (i.e. the working directory and all contained files). Files from outside this context cannot be accessed by `COPY`. When building a piped Dockerfile (i.e. `docker build -