We can use
* storage volume
* docker exec
,
* ansible (and similer software)
* docker run
with options,
* container based on container
* etc
to build a customized a docker. But with dockerfile it is easy to build a customized docker.
Share system variable¶
As discussed early, we can use a infrastructure container to share system variable to other container. (e.g use consul) and generate configure file based on system variable. e.g. a nginx file in /etc/nginx/conf.d/
Dockerfile¶
- Source code for building Docker images. It contains all the comnands to assemble a image
- Use docker build to access dockerfile
¶
Dockerfile format¶
# Comment
- INSTRUCTION arguments
- Instruction is NOT casesensitive, but it is a convention to use UPPERCASE to distinguish them from arguments more easily
- Docker runs instructions in a Dockerfile in order
- The first instruction must be
FROM
in order to specify the Base Docker Image from which your are building.
Docker ignore file .dockerignore¶
Same as .gitignore
Environment variable and replacement¶
- env variable (declared with ENV statement) can also be used in instructions as variables to be interpreted by Dockerfile
- Env variable are notated in Dockerfile with $variable_name or ${variable_name}
- ${variable_name} support bash modifiers
- ${var:-word} if var is set, return var value, otherwise return word
- ${var:+word} if var is set, return word value, otherwise return empty
¶
Dockerfile instructions¶
FROM¶
- Need to be first un-comment statement.
- Base image can be either local image or docker registry (e.g docker hub)
- Syntax (either)
- FROM \
[: ] (repository is image name e.g nginx, redis, or ray-x/busybox-httpd) - FROM \
@\ e.g.
- FROM \
¶
MAINTAINER (depreacted)¶
e.g MAINTAINER "rayxu <rayx@rayx.me>"
¶
LABELS¶
- Usage:
LABEL <key>=<value> [<key>=<value> ...]
- The LABEL instruction adds metadata to an image in format of key=value e.g
MAINTAINER="rayxu <rayx@rayx.me>"
¶
COPY¶
- Syntax:
- COPY \
[\ …] \ - COPY [“\
“, … “\ “]
- COPY \
- Copies new files or directories from
and adds them to the filesystem of the image at the path \ . - \
may contain wildcards and matching will be done using Go’s filepath.Match rules. - \
is an absolute path, or a path relative to WORKDIR. - If \
doesn’t exist, it is created along with all missing directories in its path. - If space existed in \
use “ ” e.g. “my src folder”
¶
ADD¶
ADD is similar to COPY, expects that it can add and unzip compressed file (gz, Z, bz2, zip). It also can fetch files from URL e.g. ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/local/
or nginx-1.18.0.tar.gz /usr/local
(will untar to /usr/local, docker will have /usr/local/nginx-1.18.0)
* Syntax:
* ADD \ADD ["<src>", ... "<dest>"]
and wildcard existed in src, \/
if \/
it will be treat as a single file instead of a dir
¶
WORKDIR¶
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction. * Syntax: * WORKDIR /path/to/workdir
- WORKDIR can be used multiple time
- WORKDIR instruction can resolve environment variables
¶
VOLUME¶
The VOLUME instruction creates a mount point(volume) and marks it as holding externally mounted volumes from native host or other containers.
* Syntax:
* VOLUME \-v
option in docker run
command. Difference is that VOLUME does not specify the directory mapping. Normally is uses to gether the logs in container. More specific, VOLUME /var/log will expose the folder to a folder like /var/lib/docker/volumes/3207....84e4
and docker container will know the mapping. Any logs in /var/log in docker will also appear in /var/lib/docker/volumes/3207....84e4
¶
EXPOSE¶
Specify the port/protocol container listens on at runtime.
* Syntax:
EXPOSE \
EXPOSE 11211/upp 11211/tcp 2 323/tcp
EXPOSE 80
(default tcp)
Check the port with docker port image-name
¶
ENV¶
ENV sets the environment variable \docker build
also it will be passed to docker run
The ENV setup can be overwrite with docker run -e <key>=<value>
* Syntax:
ENV \
- Refer to the env variable with $variable_name or ${variable_name}
- e.g
ENV myName John Doe
equal toENV myName="John Doe"
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
* To set a value for a single command, use RUN \
¶
RUN¶
Run the executable in docke durning docker build. The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.
- Syntax
- RUN \
(shell form, /bin/sh -c \ ) - RUN [“executable”, “param1”, “param2”] (exec form)
- Shell form PID not 1 and can not receive Unix signals
- Usage
- exec form does not support shell operator (e.g wildcard, &, >, | etc) to use shell , you need to run
RUN ["/bin/bash", "-c", "<command>", "<argument1>", "<argument2>" ... ]
¶
nohub, exec¶
Tp prevent demon stop after shell stops, need to use nohub or exec.
Note: nohub command exec: replaces the current process image with a new process image. This means it replace nohub: no hungup, Run a Command or Shell-Script Even after You Logout
CMD¶
The main purpose of a CMD is to provide defaults for an executing container. e.g. buxybox default CMD is /usr/sh, nginx default is nginx * Syntax * CMD [“executable”,”param1”,”param2”] (exec form, this is the preferred form) * CMD [“param1”,”param2”] (as default parameters to ENTRYPOINT) * CMD command param1 param2 (shell form) * If multipule CMD provided, only the last one is effective * To build a busybox httpd, which is correct: * Pitfull * CMD /bin/httpd -f -h \({WEB_ROOT} * CMD ["/bin/httpd", "-f", "-h", "\)”] * CMD [“/bin/sh”, “-c”, “/bin/httpd”, “-f”, “-h ${WEB_ROOT}”] * CMD [“/bin/sh”, “-c”, “/bin/httpd”, “-f”, “-h /opt/data/web”] * form 1, you can not enter interative mode with -it, If you need to inspect, need to run `docker exec ‘/bin/sh’ * form 2, will not work, ${WEB_ROOT} not found * form 3, will not work, start and then exit(httpd is a backend deamon sh -c httpd will return so PID 1 will exit too, this will stop the container) * form 4, will not work, start and then exit(same as above)
¶
ENTRYPOINT¶
An ENTRYPOINT allows you to configure a container that will run as an executable.
* Syntax
* ENTRYPOINT [“executable”, “param1”, “param2”] (exec form)
* ENTRYPOINT command param1 param2
* Command line arguments to docker run \
- Only the last ENTRYPOINT instruction in the Dockerfile will have an effect.
docker run --entrypoint <cmd> <args>
overwrite the ENTRYPOINT in dockerfile- ENTRYPOINT solve the issue that
CMD ["/bin/sh", "-c", "/bin/httpd", "-f", "-h /opt/data/web"]
hasENTRYPOINT /bin/httpd -f =h /opt/data/web
will not exit - If both CMD and ENTRYPOINT exists, arguments of CMD will be pass to ENTRYPOINT as argument
is eqal to
is eqal to
if you run
docker run --name bbxhttpd -it -P bbxhttpd:v0.1 "ls /opt"
“ls /opt” will overwrite CMD["/bin/httpd", "-f", "-h", "/opt/data/web"]
- Use ENTRYPOINT to set ENV var and start deamon
file: entrypoint.sh
#!/bin/sh
cat > /etc/nginx/conf.d/www.conf << EOF
server {
server_name ${HOSTNAME};
listen${IP:-0.0.0.0}:${PORT:-80}
root ${NGX_DOC_ROOT:-/usr/share/nginx/html}
}
EOF
exec "$@" # PID=1
file Dockerfile
FROM nginx:1.18-alpine
ENV NGX_ROOT="/usr/data/html"
ADD index.html ${NGX_ROOT}
ADD entrypoint.sh /bin/
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
Run:
login into docker$ docker exec -it ngx1 /bin/sh
# ps
PID USER TIME COMMAND
1 ROOT 0:00 nginx: master proccess /usr/bin/nginx -g daemon off;
You will see nginx started and use ROOT user. That is not good for security reason
#
### USER
User name for RUN, CMD, ENTRYPOINT
* Syntax
* USER \
¶
HEALTHCHECK¶
The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working. (e.g. not responding, infinite loop) Syntax * HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container) * The options that can appear before CMD are: * –interval=DURATION (default: 30s) * –timeout=DURATION (default: 30s) * –start-period=DURATION (default: 0s) * –retries=N (default: 3) * Response: * 0: success - the container is healthy and ready for use * 1: unhealthy - the container is not working correctly * 2: reserved - do not use this exit code * HEALTHCHECK NONE (disable any healthcheck inherited from the base image) example:
A more complex example
FROM nginx:1.18-alpine
ENV NGX_ROOT="/usr/data/html"
ADD index.html ${NGX_ROOT}
ADD entrypoint.sh /bin/
EXPOSE 80
HEALTHCHECK --start-period = 3s --interval=10 --timeout=1s CMD wget -O - -q http://{IP:-0.0.0.0}:${PORT:-80}/
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
docker run --name web1 --rm -P -e "PORT=8080" ngx:v0.1
127.0.0.1 - - [10/May/2020:18:11:20 +0000] "GET / HTTP/1.1" 200 32 "-" "Wget" "-"
127.0.0.1 - - [10/May/2020:18:11:23 +0000] "GET / HTTP/1.1" 200 32 "-" "Wget" "-"
¶
SHELL¶
The SHELL instruction allows the default shell used for the shell form of commands to be overridden. The default shell on Linux is [“/bin/sh”, “-c”], and on Windows is [“cmd”, “/S”, “/C”]. The SHELL instruction must be written in JSON form in a Dockerfile.
* Syntax
* SHELL [“executable”, “parameters”]
* Example
* SHELL ["powershell", "-command"]
* SHELL ["/usr/bin/zsh", "-c"]
¶
STOPSIGNAL¶
sets the system call signal that will be sent to the container to exit. * Syntex * STOPSIGNAL signal
¶
ARG¶
The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the –build-arg
example:
Use –build-arg to pass the ARG indocker build --build-arg auther="ray-x rayx@mail.com"
¶
ONBUILD¶
The ONBUILD instruction adds a trigger instruction to be executed at a later time, when the image is used as the base for another build.
The trigger will be executed in the context of the downstream build, as if it had been inserted immediately after the FROM instruction in the downstream Dockerfile.
* Syntax
* ONBUILD \ONBUILD ONBUILD CMD ["ls"]
is illegal
* Use onbuild tag for base image has onbuild
* COPY, ADD may not work....(different context)
e.g. docker nginx1:v0-onbuild