Docker 学习笔记

环境

Ubuntu16.04

安装Docker CE

若之前安装过老版本的docker,先卸载

sudo apt-get remove docker docker-engine docker.io containerd runc

1.更新apt包索引

sudo apt-get update

2.安装软件包支持apt使用基于Https的仓库

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

3.添加Docker官方的GPG key

# 官方 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 中科大镜像
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

验证key

sudo apt-key fingerprint 0EBFCD88

4.添加Docker仓库

# 官方
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
# 中科大 速度快一点
sudo add-apt-repository \
   "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

5.更新apt包索引

sudo apt-get update

6.安装最新的Docker CE

sudo apt-get install docker-ce docker-ce-cli containerd.io

查看版本信息

查看Docker版本

docker --version

Docker version 18.09.3, build 774a1f4

查看更多Docker信息,docker version 或者 docker info,这里使用sudo,否则会出现权限错误

$ sudo docker info

一般使用docker命令得加上sudo,为了避免出现权限错误 ,设置把用户加入到docker组中 Read more.

创建docker用户组,可能会提示已经存在

sudo groupadd docker

把用户添加到docker用户组

sudo usermod -aG docker $USER

登出账号

logout

然后重新登录,现在不加sudo也可以使用

docker info

测试

通过运行一个简单的image来测试Docker

$ docker run hello-world

Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/library/hello-world/manifests/latest: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Fhello-world%3Apull&service=registry.docker.io: net/http: request canceled (Client.Timeout exceeded while awaiting headers).
See 'docker run --help'.

错误解决:

打开/etc/docker/daemon.json,如果不存在创建文件,添加内容

{
  "registry-mirrors": [
    "http://141e5461.m.daocloud.io"
  ]
}

重启Docker服务

sudo service docker restart

再次运行

$ docker run hello-world

查看下载的image

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        2 months ago        1.84kB

列出所有的容器,不加--all默认列出仍在运行的容器,hello-world输出语句后就结束了,因此不加--all就看不到hello-world容器

docker container ls --all

Containers

简单来说,Container就是包含运行环境,代码,以及构建运行命令的容器,他和传统运行程序的区别就是环境不随宿主机的环境变化,自己拥有自己的一套运行环境,环境变量,可以通过端口与宿主机交流信息。下面示例构建了一个容器:

在新建文件夹下,添加三个文件

Dockerfile

# 程序运行需要的环境,也是一个镜像
# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# 需要运行的命令,这里使用pip安装需要的模块
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# 暴露80端口
# Make port 80 available to the world outside this container
EXPOSE 80

# 定义环境变量
# Define environment variable
ENV NAME World

# 当容器运行的时候执行的命令
# Run app.py when the container launches
CMD ["python", "app.py"]

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "cannot connect to Redis, counter disabled"

    html = "

Hello {name}!

" \ "Hostname: {hostname}
" \ "Visits: {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)

构建应用

当前的目录结构

$ ls
Dockerfile      app.py          requirements.txt

--tag设置镜像的名字,可以使用-t代替

docker build --tag=friendlyhello

查看镜像,这里显示了所有本地镜像,包括刚构建的以及从远程仓库下载的

$ docker image ls

运行应用

$ docker run -p 4000:80 friendlyhello

-p 4000:80将宿主机的4000端口映射到容器的80端口

访问http://宿主机IP:4000

[图片上传失败...(image-41cadb-1582005529611)]

在终端按CTRL+C停止容器

在后台运行app

$ docker run -d -p 4000:80 friendlyhello

d5d06d6b7efc6c9e8e2e730ee0139c78200951743df80afd0ce2bc604da917a1

d5d06d6b7efc6c9e8e2e730ee0139c78200951743df80afd0ce2bc604da917a1是容器ID,每个运行的容器实例都有一个ID

查看运行的容器

$ youthful_mirzakhani

停止运行app

 docker container stop d5d06d6b7efc

或者

docker container stop youthful_mirzakhani

youthful_mirzakhani是实例的NAMES属性

分享镜像

使用官方Registry非常慢,这里只是学习一下,建议使用其他Registry 阿里云容器镜像服务的基本使用

Docker支持将镜像上传到一个类似GithubMaven的公共仓库,需要在 hub.docker.com 注册账号

登录Docker账号

$ docker login

为镜像打标签

格式

$ docker tag image username/repository:tag

例如

$ docker tag friendlyhello vczyh/get-started:part2
$ docker image ls

发布镜像

$ docker push username/repository:tag

拉取镜像并运行

$ docker run -p 4000:80 username/repository:tag

Services

在分布式应用中,不同的部分被称为服务。比如,你想做一个视频分享网站,网站可能包括存储服务,用户上传视频后的转码服务,前台服务等。

服务实际上只是生产中的容器,一个服务仅运行一个镜像,但它通过编码决定了镜像的运行方式——使用的端口,运行副本的数量,便于容器拥有它所需要的容量等。拓展服务改变了运行软件的容器实例数量,从而为进程中的服务分配更多的资源。

幸运的是,使用Docker平台定义、运行和扩展服务非常容易——只需编写一个docker-compose.yml文件。

docker-compose.yml文件是一个YAML文件,它定义Docker容器在生产环境中的行为。

docker-compose.yml

version: "3"
services:
  # 定义一个叫web的服务
  web:
    # 镜像,本地或者远程
    # replace username/repo:tag with your name and image details
    # image: username/repo:tag
    image: registry.cn-hangzhou.aliyuncs.com/zhangyuheng/hello 
    deploy:
      # 包含5个副本
      replicas: 5
      resources:
        limits:
          # 每个副本最多使用10%的CPU
          cpus: "0.1"
          # 每个副本最多使用50M内存空间
          memory: 50M
      restart_policy:
        # 如果有任何一个失败,则立即重启
        condition: on-failure
    ports:
      # 将主机4000端口映射到web服务的80端口
      - "4000:80"
    networks:
      # 指示web容器通过称为webnet的负载均衡网络共享80端口(在内部,容器本身在一个临时端口上发布到web的80端口。)
      - webnet
networks:
  # 使用默认设置定义webnet网络(一个负载均衡的覆盖网络)。
  webnet:

运行你的负载均衡应用

首先先运行:

$ docker swarm init

getstartedlab是app的名字:

$ docker stack deploy -c docker-compose.yml getstartedlab

Creating network getstartedlab_webnet
Creating service getstartedlab_web

现在单个服务堆栈在一台主机上运行了5个已部署镜像的实例

查看服务:

$ docker service ls

也可以这样查看服务:

$ docker stack services getstartedlab 

服务中运行的单个容器称为任务。任务被赋予惟一的id,这些id在数字上递增,直到您在docker-comp.yml中定义的副本的数量。

列出你的服务任务:

$ docker service ps getstartedlab_web 

也可以通过查看容器来查看任务:-q仅仅列出容器ID

$ docker container ls

浏览器多次访问:http://localhost:4000

或者多次输入:

$ curl -4 http://localhost:4000

可以看到显示的Hostname(容器ID)每次都不一样,也验证了轮询方式的负载均衡

显示一个stack的所有任务:

$ docker stack ps getstartedlab

拓展应用

可以通过改变replicas 的值来拓展应用:

docker-compose.yml

 deploy:
      # 包含5个副本
      replicas: 7
$ docker stack deploy -c docker-compose.yml getstartedlab

Docker更新服务不需要关掉服务或者关掉任何容器

查看目前的容器和任务:

$ docker stack ps getstartedlab

移除应用

$ docker stack rm getstartedlab

移除集群

$ docker swarm leave --force

常用命令

docker stack ls                                            # List stacks or apps
docker stack deploy -c    # Run the specified Compose file
docker service ls                 # List running services associated with an app
docker service ps                   # List tasks associated with an app
docker inspect                    # Inspect task or container
docker container ls -q                                      # List container IDs
docker stack rm                              # Tear down an application
docker swarm leave --force      # Take down a single node swarm from the manager

Swarms

安装docker-machine

$ base=https://github.com/docker/machine/releases/download/v0.16.0 &&
  curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
  sudo install /tmp/docker-machine /usr/local/bin/docker-machine

这个岂止是慢,根本就没速度,所以采用手动安装,先去https://github.com/docker/machine/releases/下载,这里下载也得翻墙==

下载好安装:

$ sudo install docker-machine-Linux-x86_64 /usr/local/bin/docker-machine

验证:

$ docker-machine version

docker-machine version 0.16.0, build 702c267f

创建虚拟机集群

安装virtualbox驱动:

$ sudo apt install virtualbox

创建名为myvm1的虚拟机:

$ docker-machine create --driver virtualbox myvm1

Running pre-create checks...
Error with pre-create check: "This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory"

出现错误,这里使用的是VMware,解决:

Docker 学习笔记_第1张图片
在这里插入图片描述
$ docker-machine create --driver virtualbox myvm1

从github下载iso文件非常慢,采用手动下载,参考:

iso文件放到默认位置:

$ cp boot2docker.iso ~/.docker/machine/cache/
$ docker-machine create --driver virtualbox myvm1

Running pre-create checks...
Creating machine...
(myvm1) Copying /home/vczyh/.docker/machine/cache/boot2docker.iso to /home/vczyh/.docker/machine/machines/myvm1/boot2docker.iso...
(myvm1) Creating VirtualBox VM...
(myvm1) Creating SSH key...
(myvm1) Starting the VM...
(myvm1) Check network to re-create if needed...
(myvm1) Found a new host-only adapter: "vboxnet0"
(myvm1) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env myvm1

同样,再创建一个名为myvm2的虚拟机:

$ docker-machine create --driver virtualbox myvm2

查看虚拟机:

$ docker-machine ls  

连接虚拟机

$ docker-machine --native-ssh ssh myvm1
docker@myvm1:~$ 

初始化swarm以及添加节点

连接myvm1后:指定myvm1swarm manager192.168.99.100myvm1的IP

docker@myvm1:~$ docker swarm init --advertise-addr 192.168.99.100

CTRL+D退出连接,连接myvm2后:设置myvm2swarm worker

docker@myvm2:~$ docker swarm join --token SWMTKN-1

现在一个swarm已经创建完成

swarm manager(myvm1)中查看所有节点:

docker@myvm1:~$ docker node ls

另外一种与虚拟机对话方式

$ docker-machine env myvm1

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/sam/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell:
# eval $(docker-machine env myvm1)

运行:

eval $(docker-machine env myvm1)

现在实现了和ssh连接myvm1相同的结果:

docker node ls

好处之一就是虚拟机可以直接使用宿主机的文件

断开对话:

eval $(docker-machine env -u)

部署应用到swarm

使用eval $(docker-machine env myvm1)打开与myvm1的对话

$ docker stack deploy -c docker-compose.yml getstartedlab

如果docker-compose.yml里使用的镜像不是Docker Hub的:

docker login registry.example.com

docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab
$ docker stack ps getstartedlab 

现在5个实例(容器)已经分布在俩个虚拟机中

查看myvm1的容器:其他的3个实例在myvm2

$ docker container ls

测试

宿主机运行:192.168.99.101是任意一个虚拟机的IP

curl 192.168.99.101:4000

每次访问的Hostname不同,证实了集群的负载均衡

拓展应用

第一种:修改docker-compose.yml

第二种:使用docker swarm join为集群添加机器

这俩种操作之后,重新执行docker stack deploy -c docker-compose.yml getstartedlab

关闭应用

关闭stack

docker stack rm getstartedlab

关闭swarm:

docker swarm leave  // worker
docker swarm leave --force // manager

常用命令

docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux)
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10
docker-machine env myvm1                # View basic information about your node
docker-machine ssh myvm1 "docker node ls"         # List the nodes in your swarm
docker-machine ssh myvm1 "docker node inspect "        # Inspect a node
docker-machine ssh myvm1 "docker swarm join-token -q worker"   # View join token
docker-machine ssh myvm1   # Open an SSH session with the VM; type "exit" to end
docker node ls                # View nodes in swarm (while logged on to manager)
docker-machine ssh myvm2 "docker swarm leave"  # Make the worker leave the swarm
docker-machine ssh myvm1 "docker swarm leave -f" # Make master leave, kill swarm
docker-machine ls # list VMs, asterisk shows which VM this shell is talking to
docker-machine start myvm1            # Start a VM that is currently not running
docker-machine env myvm1      # show environment variables and command for myvm1
eval $(docker-machine env myvm1)         # Mac command to connect shell to myvm1
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression   # Windows command to connect shell to myvm1
docker stack deploy -c    # Deploy an app; command shell must be set to talk to manager (myvm1), uses local Compose file
docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app)
docker-machine ssh myvm1 "docker stack deploy -c  "   # Deploy an app using ssh (you must have first copied the Compose file to myvm1)
eval $(docker-machine env -u)     # Disconnect shell from VMs, use native docker
docker-machine stop $(docker-machine ls -q)               # Stop all running VMs
docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images

Docker其他配置

镜像配置

/etc/docker/daemon.json

{
  "registry-mirrors": [
    "http://141e5461.m.daocloud.io"
  ]
}
sudo service docker restart

DNS配置

Docker实例里的DNS可能出问题,所以配置Docker使用的DNS

/etc/docker/daemon.json

{
  "dns": ["your_dns_address", "8.8.8.8"]
}
sudo service docker restart

你可能感兴趣的:(Docker 学习笔记)