docker笔记

docker笔记

1. VirtualMachine Vs Container

virtualMachine_vs_container

What's the Difference:

VMS Containers
Heavyweight Lightweight
Each VM runs in its own OS All containers share the host OS
Startup time in minutes Startup time in milliseconds
More memory / disk space less memory / space
Fully isolated and hence more secure Process-level isolation, possibly less secure

Types of Containers:

  1. LXC
  2. Docker

Ref: https://www.backblaze.com/blog/vm-vs-containers/


2. Docker Architecture

docker_architecture

Client/Server Architecture

  • Server: It is the docker daemon called dockerd. It's the one that create/manage images, container, network etc..

  • Client: Enable users to interact with Docker.The Docker client can reside on the same host as the daemon or connect to a daemon on a remote host. Docker client provides a command line interface (CLI) that allows you to issue build, run, and stop application commands to a Docker daemon.


3. Installation

https://docs.docker.com/v17.09/engine/installation/#desktop

docker --version

docker run hello-world


4. Docker Image

Docker images are read-only templates with instructions to create a docker container.

Image Layer

image_layer

4.1 Using Dockerfile

Steps:

  1. Create Dockerfile

  2. Run docker build ${Dockerfile Directory}

    docker build -t ${tagname} ${Dockerfile Directory}

  3. Push img to repository

eg nodejs express

FROM node:10
# create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .
EXPOSE 8099
CMD [ "npm", "start" ]
  • BaseImg: node:10(https://hub.docker.com/_/node?tab=description&page=1)
  • Copy package.json, package-lock.json
  • Install dependency
  • Copy Js file
  • EXPOSE port (8099 in this case)
  • CMD, instruct what command should be run for the container of this IMG

https://docs.docker.com/engine/reference/builder/

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/


4.2 Creating a Docker Image from an Existing Container

Only when don't have dockerFile inhand while you want to customize on top of existing Img.

4.3 Docker Img CMD

docker image ls 
docker rmi IMAGE [IMAGE]

5. Docker repository

5.1 DockerHub

Public vs Private:

https://docs.docker.com/docker-hub/repos/

https://hub.docker.com/pricing

  • Tag Image

    docker tag {img} zseashellhb/hello-nodejs:1.0

  • Login

    docker login

  • Push to DockerHub

    docker push zseashellhb/hello-nodejs:1.0

  • Pull img

    docker pull zseashellhb/hello-nodejs:1.0

5.2 jfrog docker registry

https://jfrog.com/integration/docker-registry/

5.3 IBM CLoud Container Registry

https://www.ibm.com/cloud/container-registry

6. Docker container

When you run a docker image, it creates a docker container. Conainer is an “instance” of the image.

Container Layer

The major difference between a container and an image is the top writable layer. All writes to the container that add new or modify existing data are stored in this writable layer. When the container is deleted, the writable layer is also deleted. The underlying image remains unchanged.

container_layer

Sample: Run container for Img zseashellhb/hello-nodejs


docker run -p 9099:8099 -d zseashellhb/hello-nodejs

(Running your image with -d runs the container in detached mode, leaving the container running in the background. The -p flag redirects a public port to a private port inside the container.)

Testing

curl -i localhost:9099

docker logs -f <container id>
LifeCycle

docker stop [containerId]

docker restart [containerId]

docker kill [OPTIONS] CONTAINER

docker rm [OPTIONS] CONTAINER

7. Docker Volumes

By default all files created inside a container are stored on a writable container layer. This means that:

The data doesn’t persist when that container is no longer running, and it can be difficult to get the data out of the container if another process needs it.
A container’s writable layer is tightly coupled to the host machine where the container is running. You can’t easily move the data somewhere else.
Writing into a container’s writable layer requires a storage driver to manage the filesystem. The storage driver provides a union filesystem, using the Linux kernel. This extra abstraction reduces performance as compared to using data volumes, which write directly to the host filesystem.

Good use cases for volumes

Volumes are the preferred way to persist data in Docker containers and services. Some use cases for volumes include:

* Sharing data among multiple running containers. If you don’t explicitly create it, a volume is created the first time it is mounted into a container. When that container stops or is removed, the volume still exists. Multiple containers can mount the same volume simultaneously, either read-write or read-only. Volumes are only removed when you explicitly remove them.

* When the Docker host is not guaranteed to have a given directory or file structure. Volumes help you decouple the configuration of the Docker host from the container runtime.

* When you want to store your container’s data on a remote host or a cloud provider, rather than locally.

* When you need to back up, restore, or migrate data from one Docker host to another, volumes are a better choice. You can stop containers using the volume, then back up the volume’s directory (such as /var/lib/docker/volumes/<volume-name>).

Example: couchDB

https://docs.couchdb.org/en/stable/install/docker.html

https://github.com/apache/couchdb-docker

docker run -p 5984:5984 -v ~/docker-volume/data:/opt/couchdb/data apache/couchdb:2

Try http://localhost:5984/_utils/

Testing persistence : restart container still can get access to data

  1. create a DB

    curl -X PUT http://127.0.0.1:5984/test_db

  2. Populate Data

curl -X POST \
-H "Content-Type: application/json" \
-H 'Accept:application/json' \
-d '{"Value": "Hello CouchDB"}' \
http://127.0.0.1:5984/test_db

  1. Kill and Remove the container
docker kill ?
docker rm ?
  1. Start another container using same mount

```` docker run -p 5984:5984 -v ~/docker-volume/data:/opt/couchdb/data apache/couchdb:2


## 8. Docker Compose

https://docs.docker.com/compose/overview/

https://docs.docker.com/compose/gettingstarted/

> app.py

```python
import time
import redis

from flask import Flask


app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
retry_counter = 0
retries = 3
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
retry_counter += 1
print("Retry for %s times..." % retry_counter)
time.sleep(0.5)


@app.route('/')
def hello():
print(">>>Received Request")
count = get_hit_count()
return 'Hello World From Docker! I have been see {} times.\n'.format(count)


if __name__ == '__main__':
app.run(host="0.0.0.0", debug=True)


> Dockerfile

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

Docker-compose.yml


version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:5"
docker-compose up

docker-compose down
  • refresh page
  • check redis

docker exec -it docker-compose_redis_1 sh

docker run -it --link docker-compose_redis_1 --net docker-compose_default --rm redis:5 redis-cli -h redis -p 6379


KEYS *
GET hits

9. Debugging

Docker Logs

https://docs.docker.com/engine/reference/commandline/logs/#extended-description

Docker Inspect

https://docs.docker.com/engine/reference/commandline/inspect/

Docker Exec

https://docs.docker.com/engine/reference/commandline/exec/#run-docker-exec-on-a-running-container

docker exec -ti {} sh -c "ps -aux"

docker exec -it {} bash

10. Tools

  • Portainer

    https://www.portainer.io/

  • Kitematic

    https://github.com/docker/kitematic

11. Orchestration

  • Docker Swarm
  • Kubernetes
  • Apache Mesos

https://blog.newrelic.com/engineering/container-orchestration-explained/