-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Use staged container builds to improve caching and reduce size (#727)
* - Use staged container builds to improve caching and reduce size - Image size reduced from 8 GB to 1.6ish - Switched from Make to Ninja for faster builds that do not hog processor - Removed unneded dependencies - Added to .dockerignore - Readme for docker stuff - Staged Builds - Docker's overlay FS means that `rm`ing files does not reduce size - Once build artifacts are build, the build dependencies are no longer needed - Both of these can be solved by building in a temporary image and copying only the needed libraries in - Leverages DESTDIR to generate a directory structure that can be just copied onto the `/` of the filesystem - Similarly, the data files (like models) can be downloaded ahead of time into their own image and copied in. This saves on network IO. - Anything in a RUN directive that is non-deterministic (e.g. downloading a file from a link, the content of that link changes) does not cause a cache miss, so if you need to update something RUN uses, either modify the dockerfile or build with `--no-cache` to force a rebuild - Switch to Ninja - cmake can generate many types of build systems - Ninja builds faster than GNU Make - `make -j` has a tendency to lock up my system when building locally - Do not need to tell ninja how many jobs to run - .dockerignore - Paths in .dockerignore are basically invisible to dockerd, so when dockerd zips up the build context, all of the cruft can be ignored - it is beneficial to docker build speed to add any large, unnecssary files and directories to .dockerignore. - Just remember they cannot be seen by dockerd * removing cruft and some format fixes * updated dockerfile to opencv 4.1.0
- Loading branch information
1 parent
397a58d
commit b802889
Showing
8 changed files
with
206 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
.git | ||
docker-compose.yml | ||
build | ||
matlab_runners | ||
matlab_version | ||
python_scripts | ||
test-dump | ||
samples | ||
model_training | ||
gui | ||
gui |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
## This is read by docker-compose. You can overwrite these at runtime, e.g.: | ||
## DOCKERUSER=bobfoo docker-compose build | ||
|
||
DOCKERUSER=openface | ||
DOCKERTAG=latest | ||
DATA_MOUNT=/tmp/openface |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--- | ||
# Variables can be set from the shell: `DOCKERTAG=foo docker-compose build` | ||
# or from a .env file. See docker-compose documentation for details | ||
# Variable DOCKERUSER should be set to your dockerhub user | ||
# Alternatively, use a docker registry url as the image name | ||
version: '3.7' | ||
services: | ||
## Image runtime service | ||
## This can be used to add volume mounts or pass environment variables | ||
## Todo: make a service which can use the container interactively | ||
openface: | ||
container_name: openface | ||
build: | ||
context: . | ||
dockerfile: docker/Dockerfile | ||
image: "${DOCKERUSER}/openface:${DOCKERTAG}" | ||
tty: true | ||
volumes: | ||
- "${DATA_MOUNT}:${DATA_MOUNT}" | ||
environment: | ||
DATA_MOUNT: "${DATA_MOUNT}" | ||
command: ["bash"] | ||
|
||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# ==================== Building Model Layer =========================== | ||
# This is a little trick to improve caching and minimize rebuild time | ||
# and bandwidth. Note that RUN commands only cache-miss if the prior layers | ||
# miss, or the dockerfile changes prior to this step. | ||
# To update these patch files, be sure to run build with --no-cache | ||
FROM alpine as model_data | ||
RUN apk --no-cache --update-cache add wget | ||
WORKDIR /data/patch_experts | ||
|
||
RUN wget -q https://www.dropbox.com/s/7na5qsjzz8yfoer/cen_patches_0.25_of.dat &&\ | ||
wget -q https://www.dropbox.com/s/k7bj804cyiu474t/cen_patches_0.35_of.dat &&\ | ||
wget -q https://www.dropbox.com/s/ixt4vkbmxgab1iu/cen_patches_0.50_of.dat &&\ | ||
wget -q https://www.dropbox.com/s/2t5t1sdpshzfhpj/cen_patches_1.00_of.dat | ||
|
||
## ==================== Install Ubuntu Base libs =========================== | ||
## This will be our base image for OpenFace, and also the base for the compiler | ||
## image. We only need packages which are linked | ||
|
||
FROM ubuntu:18.04 as ubuntu_base | ||
|
||
LABEL maintainer="Michael McDermott <[email protected]>" | ||
|
||
ARG DEBIAN_FRONTEND=noninteractive | ||
|
||
# todo: minimize this even more | ||
RUN apt-get update -qq &&\ | ||
apt-get install -qq curl &&\ | ||
apt-get install -qq --no-install-recommends \ | ||
libopenblas-dev liblapack-dev \ | ||
libavcodec-dev libavformat-dev libswscale-dev \ | ||
libtbb2 libtbb-dev libjpeg-dev \ | ||
libpng-dev libtiff-dev &&\ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
## ==================== Build-time dependency libs ====================== | ||
## This will build and install opencv and dlib into an additional dummy | ||
## directory, /root/diff, so we can later copy in these artifacts, | ||
## minimizing docker layer size | ||
## Protip: ninja is faster than `make -j` and less likely to lock up system | ||
FROM ubuntu_base as cv_deps | ||
|
||
WORKDIR /root/build-dep | ||
ARG DEBIAN_FRONTEND=noninteractive | ||
|
||
RUN apt-get update -qq && apt-get install -qq -y \ | ||
cmake ninja-build pkg-config build-essential checkinstall\ | ||
g++-8 &&\ | ||
rm -rf /var/lib/apt/lists/* &&\ | ||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8 | ||
|
||
## llvm clang-3.7 libc++-dev libc++abi-dev \ | ||
## ==================== Building dlib =========================== | ||
|
||
RUN curl http://dlib.net/files/dlib-19.13.tar.bz2 -LO &&\ | ||
tar xf dlib-19.13.tar.bz2 && \ | ||
rm dlib-19.13.tar.bz2 &&\ | ||
mv dlib-19.13 dlib &&\ | ||
mkdir -p dlib/build &&\ | ||
cd dlib/build &&\ | ||
cmake -DCMAKE_BUILD_TYPE=Release -G Ninja .. &&\ | ||
ninja && \ | ||
ninja install && \ | ||
DESTDIR=/root/diff ninja install &&\ | ||
ldconfig | ||
|
||
## ==================== Building OpenCV ====================== | ||
ENV OPENCV_VERSION=4.1.0 | ||
|
||
RUN curl https:/opencv/opencv/archive/${OPENCV_VERSION}.tar.gz -LO &&\ | ||
tar xf ${OPENCV_VERSION}.tar.gz && \ | ||
rm ${OPENCV_VERSION}.tar.gz &&\ | ||
mv opencv-${OPENCV_VERSION} opencv && \ | ||
mkdir -p opencv/build && \ | ||
cd opencv/build && \ | ||
cmake -D CMAKE_BUILD_TYPE=RELEASE \ | ||
-D CMAKE_INSTALL_PREFIX=/usr/local \ | ||
-D WITH_TBB=ON -D WITH_CUDA=OFF \ | ||
-DWITH_QT=OFF -DWITH_GTK=OFF\ | ||
-G Ninja .. && \ | ||
ninja && \ | ||
ninja install &&\ | ||
DESTDIR=/root/diff ninja install | ||
|
||
## ==================== Building OpenFace =========================== | ||
FROM cv_deps as openface | ||
WORKDIR /root/openface | ||
|
||
COPY ./ ./ | ||
|
||
COPY --from=model_data /data/patch_experts/* \ | ||
/root/openface/lib/local/LandmarkDetector/model/patch_experts/ | ||
|
||
RUN mkdir -p build && cd build && \ | ||
cmake -D CMAKE_BUILD_TYPE=RELEASE -G Ninja .. && \ | ||
ninja &&\ | ||
DESTDIR=/root/diff ninja install | ||
|
||
|
||
## ==================== Streamline container =========================== | ||
## Clean up - start fresh and only copy in necessary stuff | ||
## This shrinks the image from ~8 GB to ~1.6 GB | ||
FROM ubuntu_base as final | ||
|
||
WORKDIR /root | ||
|
||
# Copy in only necessary libraries | ||
COPY --from=openface /root/diff / | ||
|
||
# Since we "imported" the build artifacts, we need to reconfigure ld | ||
RUN ldconfig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Docker building instructions | ||
|
||
This image can be build with just `docker`, but it is highly recommend to use | ||
`docker-compose` as this greatly simplifies and improves the process. | ||
|
||
## Quick start | ||
|
||
To start with the container hosted by the repo maintainer, run | ||
|
||
`docker run -it --rm --name openface algebr/openface:latest` | ||
|
||
This will drop you into a shell with binaries such as FaceLandmarkImg. For example, | ||
try this code (in the container): | ||
|
||
```bash | ||
curl -o tesla.jpg https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Nicola_Tesla_LCCN2014684845.jpg/559px-Nicola_Tesla_LCCN2014684845.jpg | ||
FaceLandmarkImg -f tesla.jpg | ||
``` | ||
|
||
Then, copy the output to the host system (from host terminal): | ||
|
||
```bash | ||
docker cp openface:/root/processed /tmp/ | ||
cd /tmp/processed | ||
``` | ||
|
||
Tip: On Ubuntu and other *nixes with X running, you can open a file directly | ||
like this: | ||
```bash | ||
xdg-open /tmp/processed/tesla.jpg | ||
``` | ||
|
||
## Building | ||
|
||
In repo root, run `docker-compose build` to automatically build and tag. | ||
There are two variables which can be used to modify the tag, `$DOCKERUSER` and | ||
`$DOCKERTAG`. DC will automatically tag image as | ||
`${DOCKERUSER}/openface:${DOCKERTAG}` | ||
|
||
## OpenFace service (in progress) | ||
|
||
To run OpenFace like a service, you can start the container with bind mounts | ||
in order to pass data into and out of the container easily. | ||
`$DATA_MOUNT` by default is set to `/tmp/openface`. This can be overridden by | ||
modifying `.env` file, setting it in your shell environment, or passing in | ||
before `docker-compose` at runtime. Note: output will be `root` owner. | ||
|
||
```bash | ||
export DATA_MOUNT=/tmp/openface | ||
mkdir -p $DATA_MOUNT/tesla # this is just to ensure this is writable by user | ||
docker-compose up -d openface && sync # sync is to wait till service starts | ||
curl -o $DATA_MOUNT/tesla.jpg \ | ||
https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Nicola_Tesla_LCCN2014684845.jpg/559px-Nicola_Tesla_LCCN2014684845.jpg | ||
docker exec -it openface FaceLandmarkImg -f $DATA_MOUNT/tesla.jpg -out_dir $DATA_MOUNT/tesla | ||
docker exec -it openface chown -R $UID:$UID $DATA_MOUNT # chown to current user | ||
docker-compose down # stop service if you wish | ||
``` |