[Docker] Docker For Beginners

Posted by Jarxi on 2020-11-08

Docker for Beginners

Container

  • Container is a running environment for IMAGE
  • port binded: talk to application running inside of container, Port 5000
  • virtual file system
  • contains application image: postgres, redis, mongo
  • in order to start the application, you will need a container so that the user can connect to the image

Basic comands

docker images prints out all images on the machine
docker run <IMAGE> runs the IMAGE, e.g. redis

1
2
3
4
5
6
7
~ docker run redis
1:C 08 Nov 2020 18:55:02.262 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 08 Nov 2020 18:55:02.263 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 08 Nov 2020 18:55:02.263 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 08 Nov 2020 18:55:02.264 * Running mode=standalone, port=6379.
1:M 08 Nov 2020 18:55:02.264 # Server initialized
1:M 08 Nov 2020 18:55:02.265 * Ready to accept connections

docker ps prints out the running container

1
2
3
 ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
035e59c5304f redis "docker-entrypoint.s…" 16 seconds ago Up 15 seconds 6379/tcp trusting_wiles

ctrl + c stops the container from running
docker run -d <IMAGE> runs IMAGE in detached mode. ctrl + c does not stop the IMAGE.
docker stop <CONTAINER_ID> ContainerID is returned by docker ps
docker start <CONTAINER_ID> starts the specific container
docker ps -a shows all the containers running or not running, so you can restart it
docker run <IMAGE>:<VERSION> if the image is not on local machine, this command pulls image and starts container
docker run -d -p <HOST_PORT>:<CONTAINER_PORT> --name <NAME> <IMAGE:VERSION> e.g. docker run -d -p 6000:6379 --name redis-latest redis:4.0 names the containers

1
2
3
~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d94bbb2ce3f6 redis "docker-entrypoint.s…" 5 seconds ago Up 4 seconds 0.0.0.0:6000->6379/tcp redis-latest

docker rmi <IMAGE>
docker rm <CONTAINER> must remove container first to remove image

Container Port vs Host Port

  • Multiple containers can run on your host machine
  • Your laptop has only certain ports available
  • Conflict when same port on host machine, but you can have the same container ports
    docker_ports.png
  • After binding host port to container port, use the port of the host. The host will forward the request to container.

Binding ports

docker run -p <HOST_PORT>:<CONTAINER_PORT> <IMAGE:TAG> e.g. docker run -p 6000:6379 redis:4.0

Trouble Shoots

docker logs <CONTAINER_ID> or docker logs <CONTAINER_NAME>
docker exec -it <CONTAINER_ID> /bin/bash or docker exec -it <CONTAINER_NAME> /bin/bash or docker exec -it <CONTAINER_NAME> /bin/sh gets the container terminal as root user
exit exits the terminal

Docker workflow

docker workflow

Demo Javascript, Node, MongoDB, MongoExpress project Local development

docker pull mongo
docker pull mongo-express

Docker network

docker network
MongoDb and Mongo Express UI are in the Isolated Docker Network. They can communicate through just the container name without localhost or port number. Application run outside of the server, such as node.js, is going to communicate through the port number.

docker package
Later if we want to deploy our application, we need to package them into the same container.

docker network ls

1
2
3
4
5
~ docker network ls
NETWORK ID NAME DRIVER SCOPE
07cdf3a9e65a bridge bridge local
ae7e2f5072ff host host local
8bcd8c145957 none null local

docker network create <NETWORK_NAME> e.g. docker network create mongo-network

1
2
~ docker network create mongo-network
085055564ae4dac7eaf73adb1650c47dca1e6bd150ff10fc6fb1ece9c7361300

Run Mongo Containers

docker run -p 27017:27017 -d \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ --name mongodb \ --net mongo-network mongo

1
2
3
4
5
6
~ docker run -p 27017:27017 -d \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
--name mongodb \
--net mongo-network mongo
e1c2847f51a26490b9dcc1d068d94c7c74fca35bff95f730fb307c61ad280b29

Mongo Environment Variables

docker logs e1c2847f51a26490b9dcc1d068d94c7c74fca35bff95f730fb307c61ad280b29 to see if the container runs successfully
docker ps gets the MONGODB_CONTAINER_NAME under NAMES, which is mongodb

1
2
3
~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1c2847f51a2 mongo "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:27017->27017/tcp mongodb

docker run -d \ -p 8081:8081 \ -e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \ -e ME_CONFIG_MONGODB_ADMINPASSWORD=password \ -e ME_CONFIG_MONGODB_SERVER=<MONGODB_CONTAINER_NAME> \ --net mongo-network \ --name mongo-express \ mongo-express

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
~ docker run -d \
-p 8081:8081 \
-e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \
-e ME_CONFIG_MONGODB_ADMINPASSWORD=password \
-e ME_CONFIG_MONGODB_SERVER=mongodb \
--net mongo-network \
--name mongo-express \
mongo-express
Unable to find image 'mongo-express:latest' locally
latest: Pulling from library/mongo-express
cbdbe7a5bc2a: Pull complete
9287919c3a0f: Pull complete
43a47bbd54c9: Pull complete
3c1bcea295c4: Pull complete
e6a871e202ed: Pull complete
02c1f0f5eb7a: Pull complete
eb9b5f9cf30d: Pull complete
eb3e7198a1e9: Pull complete
Digest: sha256:d7b5c12f4c09540c156320f1d2056aa6506df0c032b616efee9720b8dc6d6d46
Status: Downloaded newer image for mongo-express:latest
69acf98f3f5f0ed54f3c8dd1c4558074ef85263a7fceb8429a19198f96fbe3cc

Go to localhost://8081
mongo-express
Or use MongodbCompass
Connect to mongodb://admin:password@localhost:27017

Create Database
mongo-express create database

Connect Node with Mongo

connect node to mongo

Check logs

docker logs <MONGO_CONTAINER_ID> | tail
docker logs <MONGO_CONTAINER_ID> -f streams the logs. You can put a line in terminal and do some operations. Logs after the line are printed for the new opertion.

Make the docker process easier

Docker compose

docker compose mongo
docker compose mongo-express
Docker compose takes care of creating a common network. We don’t need to worry about the --net option.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# docker-compose.yaml
version: '3'
services:
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
mongo-express:
image: mongo-express
ports:
- 8080:8081
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=admin
- ME_CONFIG_MONGODB_ADMINPASSWORD=password
- ME_CONFIG_MONGODB_SERVER=mongodb

docker-compose -f <DOCKER_COMPOSE_FILENAME> up

1
docker-compose -f docker-compose.yaml up

After docker container is restarted, all of the data are gone. There is no data consistency with docker containers.
docker-compose -f <DOCKER_COMPOSE_FILENAME> down shuts up all the containers and remove the network.

Build Docker Image with Node

Build JS App &amp; Creates Docker Image

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM node:13-alpine #image name

# alternative way to specify environment variable. It's better to use docker-compose.yaml so we don't rebuild the image
ENV MONGO_DB_USERNAME=admin \
MONGO_DB_PWD=password

# creates /home/app in container, not in local machine
RUN mkdir -p /home/app

# COPY -executes on the HOST machine. COPY current direction on the host to /home/app in the container
COPY ./app /home/app

# set default dir so that next commands executes in /home/app dir
WORKDIR /home/app

# will execute npm install in /home/app because of WORKDIR
RUN npm install

# no need for /home/app/server.js because of WORKDIR
CMD ["node", "server.js"]

docker build -t my-app:1.0 .

1
2
techworld-js-docker-demo-app git:(master) ✗ docker build -t my-app:1.0 .
[+] Building 8.8s (10/10) FINISHED

docker run my-app:1.0

Demo Javascript, Node, MongoDB, MongoExpress project, Push to Docker Registry AWS ECR

Image Naming in Docker Registries

docker registry naming
tag the image so docker push push to aws instead of docker hub
docker tag my-app:1.0 <REMOTE_REPOSITORY>/my-app:1.0

Create a repository

Use web or use aws-cli
aws ecr create-repository --repository-name my-app
aws ecr get-login-password
docker login -u AWS -p <password> https://<accountid>.dkr.ecr.<your-default-region>.amazonaws.com Use the output from the previous command.

Push

docker push <REMOTE_REPOSITORY>/my-app:1.0

If you changed something

docker build -t my-app:1.1
docker tag my-app:1.1 <REMOTE_REPOSITORY>/my-app:1.1
docker push my-app:1.1 <REMOTE_REPOSITORY>/my-app:1.1

Deploy

Add new container to docker-compose.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# docker-compose.yaml on development server
version: '3'
services:
my-app:
# local docker must login to pull this repository
image: <REMOTE_REPOSITORY>/my-app:1.0
ports:
- 3000:3000
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
mongo-express:
image: mongo-express
ports:
- 8080:8081
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=admin
- ME_CONFIG_MONGODB_ADMINPASSWORD=password
- ME_CONFIG_MONGODB_SERVER=mongodb

Change the code to connect node to mongodb

replace localhost with mongodb(the container name)

Run the remote container at local machine

docker-compose -f docker-compose.yaml

Docker Volumes

If container restarts, the data is gone. We need docker volume to solve that.
Folder in physical host file system is mounted into the virtual file system of Docker.
docker volume

3 Volume Types

  1. docker run -v /home/mount/data:/var/lib/mysql/data mount host /home/mount/data to container. You decide where on the host file system the reference is made.
  2. docker run -v /var/lib/mysql/data just specify container directory. Host file automatically created by Docker, which is called anonymous volumes.
  3. docker run -v <NAME>:/var/lib/mysql/data Named Volumes. You can reference the volume by name.

Use Docker Volume in Docker Compose

docker volume compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3'
services:
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
# use where mongodb stores data, mysql:var/lib/mysql, postgres: var/lib/pstgresql/data
# <named-volume>/<mongodb-data-path>
- mongo-data:/data/db
mongo-express:
image: mongo-express
ports:
- 8080:8081
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=admin
- ME_CONFIG_MONGODB_ADMINPASSWORD=password
- ME_CONFIG_MONGODB_SERVER=mongodb
volumes:
mongo-data:
driver: local

Docker Volume Locations

linux: /var/lib/docker/volumes
mac:: /var/lib/docker/volumes
Docker for Mac creates a Linux virtual machine and stores all the Docker data there
ls /var/lib/docker returns “No such file or directory”
screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty runs the Linux vm
ls /var/lib/docker/volumes again, you see can see the volumes
ctrl + a+ k then press y you can exit the screen

Source

Docker Tutorial for Beginners [Full Course in 3 Hours]



支付宝打赏 微信打赏

赞赏一下