Below install assumes that VSCode is used as a Docker development environment. Adjust instructions appropriately if another editor is used.
Example commands are expected to be run in this repository root folder.
For personal use Docker Desktop is free and provides good and easy to setup integration with "VS Code" editor. Instructions can be found here: and here:.
For personal use Docker Desktop is free and provides good and easy to setup integration with "VS Code" editor. Instructions can be found here: and here:.
Usage of Docker Desktop is restricted in enterprise environments, therefore alternative setup is needed for such Windows environments.
- Install WSL2 with Ubuntu
- (https://ubuntu.com/tutorials/install-ubuntu-on-wsl2-on-windows-10#1-overview)
- Use version 20.04.
- Install Docker on Windows
- Integrate with WSL2
Docker Engine can be directly used from VSCode on Linux environment due to container engine and editor will run on within the same OS scope.
- Install Docker runtime (docker-ce), using yum, apt, zipper or any native package manager.
- Alternatively Docker engine installation can be followed.
- Install VSCode as defined VS Code Linux setup page.
- Install Docker Extension in VS Code as defined here.
Docker engine can be used via Linux terminal application or from within VSCode Terminal subwindow.
To build new docker image manually, run the following commands.
docker build -t app -f Dockerfile-app .
docker build -t train -f Dockerfile-train .To start up the container, you need to explicitly specify image, networking, volume and other parameters on command line.
# Run and detach from terminal
docker run -d -p 127.0.0.1:8081:5000/tcp --name training-app trainList active containers using ls and terminate them by name using kill.
docker ps
docker ps -a
docker kill train-appListing docker images and image clenup. Image clean up is needed to be done from time to time to reclaim space, used by old/unused image versions. Note, that clean up will most likely increase next build process as some build dependency images might need to be downloaded.
docker image list
docker image prune
docker image listContainer build is based on initial base image, specified in FROM definition. If image name is specified implicitly, then search is done in default public repository, usually docker.io. If an explicit name is used, then image is pulled from specified repository.
When searching for an image on https://hub.docker.com/, https://quay.io/search or other public repository, it is important to take into account image publisher. For example search for "python" results in more than "80000" hits. There have been cases of malicious content in Docker images in public repositories so a trusted publisher should be used.
It is advisable to minimize number of RUN commands in the Dockerfiles intended for production use. This allows to reduce image size due to reducing need to do multiple changes for the same FS block and smaller layer diff.
EXPOSE instruction in Dockerfile does not open ports automatically, when running container. When run with -P option, docker will pick all EXPOSE ports on random high ports. Ports can be explicitly override using -p option.
CMD instruction defines container workload application and its parameters by default. It can be overriden at run time.
TLDR version. Requires correct Compose file, though. :) Run the following command in the folder, where docker-compose.yaml does reside. Compose will parse file, fetch/build images and start applications. Access the application using http://127.0.0.1:8080/qod and get your Quote Of the Day.
NOTE: Due to public access to Quote of the day service was closed more than year ago, there no actual quotes, unfortunately. Free service allows to get only 5 quotes per day using personal auth token and implementing this was considered a bit out of scope for Compose demo.
# To run in the foreground and see logs in terminal
docker-compose up
# To disconnect from terminal and have available console
docker-compose up -d
# When finished with application stop it and dismantle networks
# Otherwise next example will fail as it will not be able to bind to 8080 port
docker-compose downWhile volumes can be defined explicilty using docker CLI, it is more convienient to define them in Docker Compose file. This is done in a docker-compose-volumes.yaml file, which has volume definitions added like the following
# Specify volume or local path and define mount point in container
volumes:
- .:/app
- logvolume:/var/log
# Define named volume
volumes:
logvolume: {}As the file name for volume usage example is not default, it needs to be explicitly specified. Also it is recommended to specify distinct project name (-p volume-example) as by default Docker assigns project name according to parent folder. In some cases running multiple Compose applications in the same project scope leads to unexpected and undesired results, like "orphaned containers found".
docker-compose -f docker-compose-volume.yaml -p volume-example up -dBinding multiple applications in compose file is done by defining container names and their dependencies. Note, that these names only define relations within YAML definition, not actual container and/or DNS names. For that, names needs to be set explicitly in Compose file. However in this case a developer is responsible for the name uniquiness. This might be needed, when linking multiple Compose applications via network as containers within same Compose are accessible via localhost.
my_app:
container_name: apache-__app_server_username__
hostname: apache-__app_server_username__In certain cases there might be a need to isolate Docker container, within container, i.e. Docker in Docker (DinD). Such inception allows completely isolate container environment from host. It is doable, however this imposes a set of issues:
- Networking for applications becomes more complex and error prone.
- Container build environment becomes more complicated as build context need to be provided to containerized Docker "host".
- This can be mitigated by locally building containers and pushing them to repo, but that mostly defeats purpose of DinD.
- To avoid serious performance penalties volumes should be defined and mounted in multiple levels to avoid writing to Copy On Write layered FS, used in containers.
Such example is defined in docker-compose-dind.yaml file.
docker-compose -f docker-compose-dind.yaml -p dind-example up -dIf checked, you should see only two docker containers running in the system. However if container list on docker "host" is verified, then actual payload will be seen.
:~/git/container-workshop$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
986ac52e9f9d docker:dind "dockerd-entrypoint.…" 16 minutes ago Up 16 minutes 2375-2376/tcp container-workshop-service-1
4f1632c0a562 docker:dind "dockerd-entrypoint.…" 16 minutes ago Up 16 minutes 2375-2376/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp container-workshop-docker-1
:~/git/container-workshop$ docker-compose -f docker-compose-dind.yaml -p dind-example ps
NAME COMMAND SERVICE STATUS PORTS
container-workshop-docker-1 "dockerd-entrypoint.…" docker running 2375-2376/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
container-workshop-service-1 "dockerd-entrypoint.…" service running 2375-2376/tcp
:~/git/container-workshop$ docker-compose -f docker-compose-dind.yaml -p dind-example exec -it docker docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9275f041586 app "python3 app.py" 16 minutes ago Up 16 minutes 0.0.0.0:8080->8080/tcp app-app-1
b7ef72934d7c redis:alpine "docker-entrypoint.s…" 16 minutes ago Up 16 minutes 6379/tcp app-redis-1
To summarize, usually it might be more efficient to design volume structure properly and isolate container files within volumes. This might be more efficient than DinD implementation, which will still require multilevel volume mounts. Usually such isolation is used on application build hosts to ensure clean build environment and avoid situation, when leftovers from previous build might affect new build and/or test statges.
More complex application examples from the Docker example/demo application repository.
Folder k8s-wordsmith-demo contains K8s Wordsmith Demo application, which selects 5 random words from random word sources, running in separate containers and presents a constructed sentence.
A simple NGinx proxy for Flask application with MySQL backend can be found in nginx-flask-mysql folder.