#90daysofdevop #19

#90daysofdevop #19

Docker Volume,Docker Network

Docker-Volume

Docker allows us to create something called volumes.

Volumes are like separate storage areas that can be accessed by containers. They allow to store data, like a database, outside the container, so it doesn't get deleted when the container is deleted. You can also mount from the same volume and create more containers having same data.

Volumes can be shared between containers.

Creating Volumes

$ docker volume create volume_name

3.2. Listing Volumes

If a name is not specified, Docker generates a random name:

$ docker volume create  
d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

Listing Volumes

$ docker volume ls
DRIVER     VOLUME NAME
local     data_volume
local   d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

Using Filter

$ docker volume ls -f name=data
DRIVER     VOLUME NAME
local     data_volume

Inspecting Volumes

$ docker volume inspect ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59

Removing Volumes

$ docker volume rm volume_name
volume_name

Pruning Volumes

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
volume_name

Starting a Container with a Volume

Using -v

$ docker run -v $(pwd):/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"

This syntax also supports mounting a volume:

$ docker run -v volume_name:/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"
$ docker run -v volume_name:/var/opt/project bash:latest \
  bash -c "echo Baeldung > /var/opt/project/Baeldung.txt"Copy

Then our subsequent use of a container with this volume mounted would be able to access the file:

$ docker run -v data-volume:/var/opt/project bash -c "ls /var/opt/project"
file.txt

The -v option contains three components, separated by colons:

  • Source directory or volume name

  • Mount point within the container

  • (Optional) ro if the mount is to be read-only

Using the –mount Option

$ docker run --mount \
  'type=volume,src=data-volume,\
  dst=/var/opt/project,volume-driver=local,\
  readonly' \ 
  bash -c "ls /var/opt/project"

The input to –mount is a string of key-value pairs, separated by commas. Here we've set:

  • type – as volume to indicate a volume mount

  • src – to the name of the volume, though this could have been a source directory if we'd been making a bind mount

  • dst – as the destination mount point in the container

  • volume-driver – the local driver in this case

  • readonly – to make this mount read-only; we could have chosen rw for read/write

Using –volumes-from to Share Volumes

$ docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED              STATUS                          PORTS      NAMES
4920602f8048   bash              "docker-entrypoint.s…"   7 minutes ago        Exited (0) 7 minutes ago                   exciting_payne

We could run our next container, by copying the volumes used by this one:

$ docker run --volumes-from 4920 \
  bash:latest \
  bash -c "ls /var/opt/project"
file.txt

In practice –volumes-from is usually used to link volumes between running containers. Jenkins uses it to share data between agents running as Docker containers.

Docker Network

Docker allows you to create virtual spaces called networks, where you can connect multiple containers (small packages that hold all the necessary files for a specific application to run) together. This way, the containers can communicate with each other and with the host machine (the computer on which the Docker is installed). When we run a container, it has its own storage space that is only accessible by that specific container. If we want to share that storage space with other containers, we can't do that.

Listing All Docker Networks

docker network ls
sudo docker network ls

Output

Docker Networks

Inspecting a Docker network

docker network inspect networkname

Options

  • networkname − This is the name of the network you need to inspect.

Return Value

The command will output all the details about the network.

Example

sudo docker network inspect bridge

Output

Inspecting Docker Network

sudo docker run –it ubuntu:latest /bin/bash

Run a Container in Network

Now if we inspect our network name via the following command, you will now see that the container is attached to the bridge.

sudo docker network inspect bridge

Container Attached to Bridge

Creating Your Own New Network

docker network create –-driver drivername name

Options

  • drivername − This is the name used for the network driver.

  • name − This is the name given to the network.

sudo docker network create –-driver bridge new_nw

Long ID

sudo docker run –it –network=new_nw ubuntu:latest /bin/bash

New Network

sudo docker network inspect new_nw

New NW

#

Docker-Volume

Docker allows us to create something called volumes.

Volumes are like separate storage areas that can be accessed by containers. They allow to store data, like a database, outside the container, so it doesn't get deleted when the container is deleted. You can also mount from the same volume and create more containers having same data.

Volumes can be shared between containers.

Creating Volumes

Bash

$ docker volume create volume_name

3.2. Listing Volumes

If a name is not specified, Docker generates a random name:

Bash

$ docker volume create  
d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

Listing Volumes

Bash

$ docker volume ls
DRIVER     VOLUME NAME
local     data_volume
local   d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

Using Filter

Bash

$ docker volume ls -f name=data
DRIVER     VOLUME NAME
local     data_volume

Inspecting Volumes

Bash

$ docker volume inspect ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59

Removing Volumes

Bash

$ docker volume rm volume_name
volume_name

Pruning Volumes

Bash

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
volume_name

Starting a Container with a Volume

Using -v

Bash

$ docker run -v $(pwd):/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"

This syntax also supports mounting a volume:

Bash

$ docker run -v volume_name:/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"

Bash

$ docker run -v volume_name:/var/opt/project bash:latest \
  bash -c "echo Baeldung > /var/opt/project/Baeldung.txt"Copy

Then our subsequent use of a container with this volume mounted would be able to access the file:

Bash

$ docker run -v data-volume:/var/opt/project bash -c "ls /var/opt/project"
file.txt

The -v option contains three components, separated by colons:

  • Source directory or volume name

  • Mount point within the container

  • (Optional) ro if the mount is to be read-only

Using the –mount Option

Bash

$ docker run --mount \
  'type=volume,src=data-volume,\
  dst=/var/opt/project,volume-driver=local,\
  readonly' \ 
  bash -c "ls /var/opt/project"

The input to –mount is a string of key-value pairs, separated by commas. Here we've set:

  • type – as volume to indicate a volume mount

  • src – to the name of the volume, though this could have been a source directory if we'd been making a bind mount

  • dst – as the destination mount point in the container

  • volume-driver – the local driver in this case

  • readonly – to make this mount read-only; we could have chosen rw for read/write

Using –volumes-from to Share Volumes

Bash

$ docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED              STATUS                          PORTS      NAMES
4920602f8048   bash              "docker-entrypoint.s…"   7 minutes ago        Exited (0) 7 minutes ago                   exciting_payne

We could run our next container, by copying the volumes used by this one:

Bash

$ docker run --volumes-from 4920 \
  bash:latest \
  bash -c "ls /var/opt/project"
file.txt

In practice –volumes-from is usually used to link volumes between running containers. Jenkins uses it to share data between agents running as Docker containers.

Docker Network

Docker allows you to create virtual spaces called networks, where you can connect multiple containers (small packages that hold all the necessary files for a specific application to run) together. This way, the containers can communicate with each other and with the host machine (the computer on which the Docker is installed). When we run a container, it has its own storage space that is only accessible by that specific container. If we want to share that storage space with other containers, we can't do that.

Listing All Docker Networks

Plain Text

docker network ls

Plain Text

sudo docker network ls

Output

Docker Networks

Inspecting a Docker network

Plain Text

docker network inspect networkname

Options

  • networkname − This is the name of the network you need to inspect.

Return Value

The command will output all the details about the network.

Example

Plain Text

sudo docker network inspect bridge

Output

Inspecting Docker Network

Plain Text

sudo docker run –it ubuntu:latest /bin/bash

Run a Container in Network

Now if we inspect our network name via the following command, you will now see that the container is attached to the bridge.

Plain Text

sudo docker network inspect bridge

Container Attached to Bridge

Creating Your Own New Network

Plain Text

docker network create –-driver drivername name

Options

  • drivername − This is the name used for the network driver.

  • name − This is the name given to the network.

Plain Text

sudo docker network create –-driver bridge new_nw

Long ID

Plain Text

sudo docker run –it –network=new_nw ubuntu:latest /bin/bash

New Network

Plain Text

sudo docker network inspect new_nw

New NW

Sample YAML File:

version : "3.3"
services:
  web:
    image: varsha0108/local_django:latest
    deploy:
        replicas: 2
    ports:
      - "8001-8005:8001"
    volumes:
      - my_django_volume:/app
  db:
    image: mysql
    ports:
      - "3306:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=test@123"
volumes:
  my_django_volume:
    external: true

Configure MySQL

version: '3.4'
services:
  super-app-db:
    image: mysql:8.0.28
    environment:
      MYSQL_DATABASE: 'super-app'
      MYSQL_ROOT_PASSWORD: '$SuperApp1'
    ports:
      - '3306:3306'
    expose:
      - '3306'

Create multi-container apps with MySQL and Docker Compose

  •   docker-compose version
    

Start MySQL

  1.  docker network create todo-app
    
  2. Start a MySQL container and attach it the network.

    BashCopy

     docker run -d 
         --network todo-app --network-alias mysql 
         -v todo-mysql-data:/var/lib/mysql 
         -e MYSQL_ROOT_PASSWORD=<your-password> 
         -e MYSQL_DATABASE=todos 
         mysql:5.7
    

    Get your container ID by using the docker ps command.

    To confirm you have the database up and running, connect to the database.

     docker exec -it <mysql-container-id> mysql -p
    

    Enter the password you used, above, when prompted.

     SHOW DATABASES;
    

    You should see the following output.

    OutputCopy

     +--------------------+
     | Database           |
     +--------------------+
     | information_schema |
     | mysql              |
     | performance_schema |
     | sys                |
     | todos              |
     +--------------------+
     5 rows in set (0.00 sec)
    

Run your app with MySQL

The todo app supports the setting of environment variables to specify MySQL connection settings.

  • MYSQL_HOST The hostname for the MySQL server.

  • MYSQL_USER The username to use for the connection.

  • MYSQL_PASSWORD The password to use for the connection.

  • MYSQL_DB The database to use once connected.

  1. Use the following docker run command. It specifies the environment variables above.

     docker run -dp 3000:3000 
       -w /app -v ${PWD}:/app 
       --network todo-app 
       -e MYSQL_HOST=mysql 
       -e MYSQL_USER=root 
       -e MYSQL_PASSWORD=<your-password> 
       -e MYSQL_DB=todos 
       node:12-alpine 
       sh -c "yarn install && yarn run dev"
    

    use the docker logs command.

    Enter http://localhost:3000 into your browser. Add some items to your todo list.

    Connect to the MySQL database, as you did in the previous section. Run this command to verify that the items are being written to the database.

     docker exec -ti <mysql-container-id> mysql -p todos
    
     select * from todo_items;
    

Create a Docker Compose file

Docker Compose helps define and share multi-container applications. With Docker Compose, you can create a file to define the services. With a single command, you can spin up everything or tear it all down.

  1. At the root of the app project, create a file named docker-compose.yml.

  2. In the compose file, start by defining the schema version.

    YAMLCopy

     version: "3.7"
    
  3. Define the services, or containers, you want to run as part of your application.

    YAMLCopy

     version: "3.7"
    
     services:
    
     version: "3.7"
    
     services:
       app:
         image: node:12-alpine
    
     version: "3.7"
    
     services:
       app:
         image: node:12-alpine
         command: sh -c "yarn install && yarn run dev"
    
     version: "3.7"
    
     services:
       app:
         image: node:12-alpine
         command: sh -c "yarn install && yarn run dev"
         ports:
           - 3000:3000
    
  4. Specify the working directory and the volume mapping

    YAMLCopy

     version: "3.7"
    
     services:
       app:
         image: node:12-alpine
         command: sh -c "yarn install && yarn run dev"
         ports:
           - 3000:3000
         working_dir: /app
         volumes:
           - ./:/app
    

    In Docker Compose volume definitions, you can use relative paths from the current directory.

     version: "3.7"
    
     services:
       app:
         image: node:12-alpine
         command: sh -c "yarn install && yarn run dev"
         ports:
           - 3000:3000
         working_dir: /app
         volumes:
           - ./:/app
         environment:
           MYSQL_HOST: mysql
           MYSQL_USER: root
           MYSQL_PASSWORD: <your-password>
           MYSQL_DB: todos
    
     docker run -d 
       --network todo-app --network-alias mysql 
       -v todo-mysql-data:/var/lib/mysql 
       -e MYSQL_ROOT_PASSWORD=<your-password> 
       -e MYSQL_DATABASE=todos 
       mysql:5.7
    

    Define the new service and name it mysql. Add your text after the app definition, at the same level of indentation.

    YAMLCopy

     version: "3.7"
    
     services:
       app:
         # The app service definition
       mysql:
         image: mysql:5.7
    

    The service automatically gets the network alias. Specify the image to use.

    Define the volume mapping.

    Specify the volume with a volumes: section at the same level as services:. Specify the volume mapping under the image.

    YAMLCopy

     version: "3.7"
    
     services:
       app:
         # The app service definition
       mysql:
         image: mysql:5.7
         volumes:
           - todo-mysql-data:/var/lib/mysql
    
     volumes:
       todo-mysql-data:
    

    Specify the environment variables.

    YAMLCopy

     version: "3.7"
    
     services:
       app:
         # The app service definition
       mysql:
         image: mysql:5.7
         volumes:
           - todo-mysql-data:/var/lib/mysql
         environment: 
           MYSQL_ROOT_PASSWORD: <your-password>
           MYSQL_DATABASE: todos
    
     volumes:
       todo-mysql-data:
    

At this point, the complete docker-compose.yml looks like this:

YAMLCopy

version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: <your-password>
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: <your-password>
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:
  1.  docker-compose up -d
    

    The -d parameter makes the command run in the background.

    You should see output like the following results.

     Creating network "app_default" with the default driver
     Creating volume "app_todo-mysql-data" with default driver
     Creating app_app_1   ... done
     Creating app_mysql_1 ... done
    

    In the Docker extension, right-click the app container and select View Logs. To view the logs from the command line, use the docker logs command.

    OutputCopy

     mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
     mysql_1  | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
     app_1    | Connected to mysql db at host mysql
     app_1    | Listening on port 3000
    

    At the command line, run docker-compose down.

docker-compose down --volumes.