Docker basics
Setting up Portainer (Docker web frontend and container manager)
Create persistent volume in local root docker install
docker volume create portainer_data
The following command will :
- Pull "portainer/portainer-ce:latest" image in local root docker
- Container publishes ports 9443 and 8000 ; docker host forward them
- Always restart with docker
- -v to map volumes host_volume:container_volume
$ sudo docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Portainer is now up and running at https://localhost:9443
Tips
Listing images is as simple as running the following :
$ sudo docker images
Images are stored in local root docker install, default is /var/lib/docker/overlay2
Docker is conservative by default ; one has to "prune" unused stuff using the prune option
$ docker image prune
$ docker network prune
$ docker volume prune
Or, to delete all unused resources :
$ docker system prune
To list containers and their status :
$ sudo docker ps
A Dockerfile is used to build custom images
One can use it with compose.yml and the $ docker-compose
command
To build the multi container app configured in ./compose.yml
$ docker-compose build
Finally, to run specified <service_name> in a new container using options specified in ./compose.yml
$ docker-compose run --rm --service-ports <service_name>
--rm
removes the container on exit
--service-ports
uses ports defined in the service configuration in the compose file
Sample Dockerfile
FROM ruby:latest #--> pulls ruby latest image from dockerhub
WORKDIR /home/app #--> image working directory can be anything
ENV PORT 3000 #--> sets up env var "PORT" inside the container to be "3000"
EXPOSE $PORT #--> expose container's "PORT" env var to the docker host
RUN gem install rails bundler #--> run arbitrary commands to set up env as wished
RUN gem install rails
RUN apt-get update -qq && apt-get install -y nodejs
ENTRYPOINT [ "/bin/bash" ] #--> command that gets executed when using docker run <this_image_container>
Sample compose.yml
services:
rails_dev: #--> sets up a service called "rails_dev"
build: . #--> when running docker-compose build use "." as the filepath where to look for the Dockerfile
container_name: rails_container #--> the container name
ports:
- "3000:3000" #--> exposing ports host:container, default ip is 0.0.0.0, can use "127.0.0.1:3000:3000"
volumes:
- ./:/home/app #--> map volumes host:container
💡 Note
A Dockerfile is used to describe and build an image.
A docker compose file is used to describe and build a container and its associated services.
Registry
Docker pulls images from what's called a registry (dockerhub @docker.io by default)
# shortcut for "docker pull docker.io/library/<image_name>"
$ docker pull <image_name>
# one can run its own registry using the official image called registry
$ docker run -d -p 5000:5000 --restart always --name registry registry:2
# tags local <image_name> with the tag "myfirstimage" in registry @localhost:5000
$ docker image tag <image_name> localhost:5000/myfirstimage
# push image with tag "myfirstimage" to registry @localhost:5000
$ docker push localhost:5000/myfirstimage
✅ Why is it cool?
One can integrate its own registry in a CI/CD workflowcommit -> git hooks or something (quality check) -> build process is triggered in CI system (automated tests) -> build succeed? -> push new image to registry and notify -> auto deploy on a staging env or simply notify other systems of the new image being available
This streamlines build process, reduces codebase discrepancy between devs and make maintenance easier for multiple versions of the same application.
Also, allows image distribution in an isolated network which is a nice privacy bonus to avoid leak of critical corporate information / leak of product intelligence.
Changing docker root directory
Running out of disk space on my /, I had to move my docker root directory in order to be able to create new volumes.
One can achieve this doing the following :
- Checking the current default docker directory
$ sudo docker info
- Stopping the docker daemon, its service AND its socket (sockets are used for triggering units, reloading confs etc.)
$ sudo systemctl stop docker.service
$ sudo systemctl stop docker.socket
$ sudo systemctl status docker
$ sudo systemctl status docker.socket
- Make a backup of the current docker configuration
$ sudo mv /etc/docker/daemon.json /etc/docker/daemon.json.old
- Edit the data-root option
$ sudo vi /etc/docker/daemon.json
{
"data-root": "/new/path/to/docker-root/"
}
- Move old content
The previous files contained in the docker root won't magically appear in the new one though.
One has to manually copy or rsync old content in the new directory.
$ sudo rsync -aP /var/lib/docker/ "/path/to/your/new/docker-root"
or
$ sudo cp -rp /var/lib/docker/* "/path/to/your/new/docker-root/"
or using symbolic links
$ ls -al docker-root/
$ ln -s /var/lib/docker/* /path/to/your/new/docker-root/
- Restart the docker daemon
$ systemctl restart docker
- Check that the newly defined path has been updated
$ docker info