Storage In Docker
- How does Docker store data?
- In particular on the local filesystem.
- Docker creates a directory structure at
/var/lib/docker/- In that directory structure, there are also
aufscontainers, imagevolumes,imagesand more. - This is where Docker stores all of its data by default.
- In that directory structure, there are also
- All files related to
containersare stored under the/var/lib/docker/containersdirectory. - Any
volumesare created under the/var/lib/docker/volumesdirectory. - How does it store the above files? Need to know the
Layered architecture - The
architectureis done via aDockerfile. It has a concept of layers:FROM Ubuntu RUN apt-get update && apt-get -y install python RUN pip install flask flask-mysql COPY . /opt/source-code ENTRYPOINT FLASK_APP=/opt/source-code/app.py flask run - Then build the image with:
docker build Dockerfile -t <repository>/<image_name> - The first layer is installing a basic Ubuntu OS
FROM Ubuntu - The second
RUN apt-getlayer makes changes at the package level. - The third layer
RUN pipmakes changes at the pip package level. - The fourth layer is copying over the source code to the
/opt/source-codedirectory. - The fifth layer is updating the
ENTRYPOINT. - Each layer only stores the changes from the previous layer, the size of each code change is reflected (for example installing the base Ubuntu OS is 120 MB, then moving to changing the apt packages is 306MB and so on)
- Consider a second application:
FROM Ubuntu RUN apt-get update && apt-get -y install python RUN pip install flask flask-mysql COPY app2.py /opt/source-code ENTRYPOINT FLASK_APP=/opt/source-code/app2.py flask run - Then building the image with the following:
docker build Dockerfile2 -t <repository>/<image_name>2 - This second application uses different source code in order to build it.
- Since the first 3 layers are the same as in the first
Dockerfile,dockerdoes not build the first 3 layers. - Then creates the last two layers, with the new entrypoint.
- Layer 4: Source code
- Layer 5: Update Entrypoint
- It builds images faster and saves disk space.
- Layers 1~3 would then be at 0MB.
- Layer 4 is the same size as from first application.
- Layer 5 has the Entrypoint updated.
- When the application code is updated,
app.pyas mentioned above,dockerreuses all of the previous layers from cache and rebuilds the application image by updating the source code.- Saves time during rebuilds and updates.
- All Layers are known as
Docker Image Layers. - Layers are read-only.
- Can only modify them by initiating a new build.
- Build the image with:
docker build Dockerfile -t <repository>/<image_name> - Run the image with:
docker run <repository>/<image_name> - Then a new Layer (Layer 6 in the above example) is created. This is a writable layer:
Layer 6: Container Layer - This layer stores logs and any file modified by the user on that container.
- When the container is destroyed, Layer 6 and all of its changes are also destroyed.
- Same image layer is shared by all containers using this image.
- Can modify files that are part of the read-only (Layers 1~5 in the previous example).
- What happens is that Docker copies these files to Layer 6, so they can be edited. It is a different version of the file and thus only in the Container Layer (Layer 6) can it be modified.
- The above two points are part of the Copy-On-Write mechanism.
- To make data persistent, then using
volumesis best.- Create a volume using the
docker volume createcommand. - For example, creating a
data_volume, makes the volume under/var/lib/docker/volumes/data_volume - The
volumesits on top of the read-only Image layer of the container. - To specify the newly created volume, run the following:
docker run -v data_volume:/var/lib/mysql mysql
- Create a volume using the
- In the above example, the image name is
mysqland stores the data under/var/lib/mysql- This creates a new container and mounts the
data_volumeinto it.
- This creates a new container and mounts the
- Even if the container is destroyed, the data is still active.
- Can also make more volumes by using this command:
docker run -v data_volume:/var/lib/mysql mysql - In addition:
docker run -v data_volume2:/var/lib/mysql mysql - To mount a volume that is not under
/var/lib/docker, run this command:docker run -v /data/mysql:/var/lib/mysql mysql - The above is called
Bind Mounting. - Ultimately two types of mounts:
Volume MountingBind Mounting
- Volume Mounting mounts a volume from the
volumesdirectory. - Bind Mounts mounts a directory from anywhere on the
dockerhost. - Using
docker run -vis the old style. - This way is better:
docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql - The
sourceis the host and thetargetis the container. - Docker uses
Storage Driversto enable the layered architecture.- Common storage drivers are
AUFS,VTRFSandZFS. - Others also include
BTRFS,Device Mapper,OverlayandOverlay2 - Ubuntu’s default
AUFS- This storage driver is not available on Fedora, CentOS.
- Device Mapper would be better in that case.
- This storage driver is not available on Fedora, CentOS.
- Common storage drivers are
Dockerchooses the best storage driver automatically based on the OS.- Different storage drivers provide different performance and stability.