Docker containers

Windows 10 administrator account fix

If Windows 10 has a separate Administrator account, do the following. Log in as Administrator and go to Start -> Computer Management -> Local Users and Groups -> Groups -> docker-users. Then add desired users to the group. Finally, log out as a user and log in again to refresh the group membership. It then will be possible to run Docker application without Administrator privileges.

Run Docker commands without sudo in Linux

Add docker group if it doesn't exist already:

sudo groupadd docker

Add the connected user to the docker group:

sudo gpasswd -a $USER docker

Log out and log in again to update group membership. Restart the docker daemon:

sudo service docker restart

Sample application

Clone the repository from Github and cd to the app folder:

git clone https://github.com/docker/getting-started.git
cd getting-started/app

Create Dockerfile in the selected folder:

# syntax=docker/dockerfile:1
FROM node:12-alpine
RUN apk add --no-cache python3 g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

Build the container using the docker build command:

docker build -t todo-app .

Start the container:

docker run -dp 3000:3000 todo-app

Delete a container

Get the ID of the running container:

docker ps

Stop the container:

docker stop <the-container-id>

Get the ID of stopped container:

docker ps -a

Remove the container:

docker rm <the-container-id>

Push the image

In order to push an image to Docker Hub, first create an account there and create a new repository. Then login to Docker Hub:

docker login -u romanak

Tag the existing image with a new name:

docker tag getting-started romanak/todo-app

Push the image to Docker Hub:

docker push romanak/todo-app

Run the image on a new instance

Go to Play with Docker and add a new instance. Then start the freshly pushed app:

docker run -dp 3000:3000 romanak/todo-app

Persist the data

Create a named volume:

docker volume create todo-db

Stop and remove the app container:

docker rm -f <id>

Start the app container, specify the named volume, and mount it to /etc/todos:

docker run -dp 3000:3000 -v todo-db:/etc/todos todo-app

Find the location where Docker is actually storing the data:

docker volume inspect todo-db

Use bind mounts

Start a dev-mode container:

docker run -dp 3000:3000 \
    -w /app -v "$(pwd):/app" \
    node:12-alpine \
    sh -c "yarn install && yarn run dev"

Watch logs:

docker logs -f <container-id>

EC2 practice

Default commands for webserver EC2 instance:

#!/bin/bash
sudo yum -y update
sudo yum -y install git
yum -y install httpd
systemctl enable httpd
systemctl start httpd
echo '<html><h1>Hello From $(hostname -f) Web Server!</h1></html>' > /var/www/html/index.html

Default commands for Docker EC2 instance:

#!/bin/bash
sudo yum -y update
sudo yum -y install git
sudo amazon-linux-extras install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user

Clone a simple Docker repository to local machine and cd to it:

git clone https://github.com/romanak/docker-getting-started.git
cd docker-getting-started

Build the getting-started image and start the container:

docker build -t getting-started .
docker run -dp 80:80 getting-started
cd app/

Build the todo-app image and start the container:

docker build -t todo-app .
docker run -dp 3000:3000 todo-app

Apply a new tag which corresponds to Docker account:

docker tag getting-started romanak/getting-started
docker tag todo-app romanak/todo-app

Login to docker and push the images to Docker Hub:

docker login -u romanak
docker push romanak/getting-started
docker push romanak/todo-app

SSH to the created EC2 instance with the created key aws.pem:

ssh -i aws.pem ec2-user@<machine-ip>

Run the Docker contaienrs from the Docker Hub in the EC2 instance:

docker run -dp 80:80 romanak/getting-started
docker run -dp 3000:3000 romanak/todo-app

Create a few items in the todo app, remove the container and create a new container from the Docker Hub image:

docker rm -f <container-id>
docker run -dp 3000:3000 romanak/todo-app

Observe that the old items have disappeared. Now remove the todo container again, create a shareable network and mysql container:

docker rm -f <container-id>
docker network create todo-app
docker run -dp 3306:3306 \
    --network todo-app --network-alias mysql \
    -v todo-mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=todos \
    mysql:5.7

Log into MySQL database container with password secret to make sure it works:

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

Use MySQL command to view the databases:

SHOW DATABASES;

Now we will deploy the todo container within the same network as MySQL database:

docker run -dp 3000:3000 \
    --network todo-app \
    -e MYSQL_HOST=mysql \
    -e MYSQL_USER=root \
    -e MYSQL_PASSWORD=secret \
    -e MYSQL_DB=todos \
    romanak/todo-app \
    sh -c "yarn install && yarn run dev"

We can check the logs of deploying the container:

docker logs <container-id>

We can add a few items to the todo list and check the database entries:

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

With the following MySQL commands:

SHOW DATABASES;
USE todos;
SHOW tables;
SELECT * FROM todo_items;

At this point we can redeploy the container and observe that the items in the todo app are preserved across different container deployments.