美文网首页
Docker学习笔记

Docker学习笔记

作者: EarthChen | 来源:发表于2017-08-22 21:21 被阅读373次

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口

随着Docker近些年越来越流行,在生产环境中也开始有较多人开始使用,Docker技术可以说成为了不得不学习的一门技术。

本文谨记录一下学习笔记,以备以后查阅。

Docker

安装Docker

使用docker官方文档里面写的安装脚本我一直安装失败,就算添加上了dcoker官方源,安装过程也会非常慢,还有一堆教程里让我们使用apt-get安装,这样的确能安装但是版本太老,这里给出一种安装非常简单的方式。

使用阿里的镜像安装

  1. 可以使用阿里云的镜像仓库下载docker-enginedocker-ce

  2. 在终端中执行以下命令

curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -

接下来只要等待就好,版本也相对够新。

  1. 查看docker版本,确认安装成功
    在终端中输入如下命令
sudo docker version
出现类似如下结果即为成功 docker版本号
  1. 使用阿里仓库来加速你的docker
    可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dmmxhzvq.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

Dockerfile

Dockerfile定义了容器中内部的环境,访问容器的网络资源和磁盘在容器是完全与外部隔离的,所以必须将你需要使用的端口映射到外部世界,并指出需要复制到该环境中的文件。

说白了Dockerfile就是一个定义容器中环境的配置文件。。

我们在这里创建一个简单的flask项目作为例子。

编写第一个Docker APP

  1. 创建一个空的文件夹,在里面创建一个文件为Dockerfile,其中的内容为
    Dockerfile为:
# Use an official Python runtime as a parent image
# 使用python3.5的官方镜像作为基础镜像(可以按需要更改)
FROM python:3.5-slim

# Set the working directory to /app
# 设置工作目录
WORKDIR /app

# Copy the current directory contents into the container at /app
# 复制当前目录下的内容到容器的/app目录下(Dockerfile同级所有目录)
ADD . /app

# Install any needed packages specified in requirements.txt
# 安装项目所需要的依赖文件requirements.txt
RUN pip install -r requirements.txt

# Make port 80 available to the world outside this container
# 让80端口能在容器外部访问
EXPOSE 80

# Define environment variable
# 定义环境便令
ENV NAME World

# Run app.py when the container launches
# 在容器启动时,运行python app.py
CMD ["python", "app.py"]
  1. flask项目的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 = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {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)

这里作为例子,只给出最简单的代码。

注:host一定要填0.0.0.0 因为这是在容器内,本机访问的127.0.0.1 和容器内不是一回事。

  1. 收集项目依赖的库,在终端输入
$ pip freeze > requirements.txt

以上执行完目录结构应该如下所示:


part1目录结构

构建APP

在编写好了你的app和Dockerfile之后,我们就可以使用Docker构建app

在终端输入docker build命令,

$ docker bulid -t docker-flask-demo .

注:

  • 如果你的系统没有将当前用户放入docker组中,请在命令前加上sudo
  • -t 命令是给你的镜像起一个友好的名字
  • 在这句命令的末尾还有一个".",代表当前目录的意思

等待上述命令完成就可以在终端执行docker images命令查看构建好的镜像

$ docker images

REPOSITORY                                                      TAG                 IMAGE ID            CREATED             SIZE
earthchen/docker-flask-demo                                     part1               3964297abb1f        About an hour ago   212MB

运行app

由于Dockerfile中的EXPOSE 80命令,容器向外只开发80端口,我们需要将外部空闲端口映射到容器的80端口

使用-p帮我们绑定端口,在终端中输入一下命令

$ docker run -p 4000:80 docker-flask-demo

在浏览器访问127.0.0.1:4000后如图

part1结果图

注: 如果需要使当前容器运行在后台,需要使用-d选项,即:

$ docker run -d -p 4000:80 docker-flask-demo

加上-d命令之后,当前只会有容器id输出,需要查看容器情况,需要使用docker ps命令

$ docker ps
或者
$ docker container ps

CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS              PORTS                  NAMES
5762ccf1dd1c        earthchen/docker-flask-demo:part1   "python app.py"     27 seconds ago      Up 26 seconds       0.0.0.0:4000->80/tcp   infallible_neumann

如果想停止运行的容器,使用docker stop命令,后面接容器id

$ docker stop 5762ccf1dd1c
或者
$ docker container stop 5762ccf1dd1c

5762ccf1dd1c

如果想删除镜像或者容器,需要先停止运行的容器,
删除容器的命令为docker rm或者是docker container rm
删除镜像的命令为docker rmi或者是docker image rm

分享你的镜像

我这里使用的是阿里云的docker Hub,如果你选择的是其他的镜像库,请自行查阅相关介绍

登录到阿里云docker registry

$ sudo docker login --username=15555000826 registry.cn-hangzhou.aliyuncs.com

给需要分享的镜像打上标签

$ sudo docker tag 5762ccf1dd1c registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1

将本地镜像推到仓库

$ sudo docker push registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1

拉取镜像

在需要部署的机器上拉取镜像,

$ docker pull registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1

part1: Pulling from earthchen/docker-flask-demo
ad74af05f5a2: Already exists 
0a004373a9cb: Already exists 
92b2e8511724: Already exists 
bc1149958e59: Already exists 
2e7ebaf17b77: Already exists 
71c4b9e65b72: Pull complete 
b668a32a73d0: Pull complete 
1e87b99f6998: Pull complete 
Digest: sha256:3b4b74a0e273a26fff42eddc077bccfb9963fd552aad766b93dc524a66c5f455
Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1

拉取完成之后就可以运行容器

$ docker run -p 4000:80 registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1

docker-compose.yml

编写第一个docker-compose.yml

docker-compose.yml的位置可以随意放置,一般放在项目根目录,
本例的docker-compose.yml的为:

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1
    deploy:
      # 运行5个镜像实体
      replicas: 5
      resources:
        limits:
          # 每个实体分配10%的cpu
          cpus: "0.1"
          # 每个实体分配50m内存
          memory: 50M
      restart_policy:
        # 如果容器失败,立即重启
        condition: on-failure
    ports:
      # 将外部4000端口映射到容易内80端口
      - "4000:80"
    networks:
      # Web容器共享端口80通过负载均衡的网络控制
      # 用默认的设置定义控制网络(这是一个负载均衡的覆盖网络)。
      - webnet
networks:
  webnet:

运行你的负载均衡app

在我们运行docker stack deploy之前时,我们需要运行以下命令

docker swarm init

不过不先执行上述命令,会产生错误

运行过后,我们就可以执行deploy命令了,我们需要给app起一个新的名字,在哪这里我们使用getstartedlab

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

Creating network getstartedlab_webnet
Creating service getstartedlab_web

运行完上述命令,就会有5个容器启动,我们可以查看一下

$ docker stack ps getstartedlab


ID                  NAME                  IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
qg7mox0vrwu1        getstartedlab_web.1   docker-flask-demo:latest   earthchen-CP65S     Running             Running 25 seconds ago                       
n7kb3qedrryx        getstartedlab_web.2   docker-flask-demo:latest   earthchen-CP65S     Running             Running 27 seconds ago                       
04tr7rp7euet        getstartedlab_web.3   docker-flask-demo:latest   earthchen-CP65S     Running             Running 27 seconds ago                       
z7yh0tvvrpwj        getstartedlab_web.4   docker-flask-demo:latest   earthchen-CP65S     Running             Running 26 seconds ago                       
z01zvjtneg3r        getstartedlab_web.5   docker-flask-demo:latest   earthchen-CP65S     Running             Running 24 seconds ago    

如果使用的是*docker ps同样能看到5个容器正在运行,只是显示的没有上述命令详细

$ docker ps

CONTAINER ID        IMAGE                      COMMAND             CREATED             STATUS              PORTS               NAMES
bccc38eb8429        docker-flask-demo:latest   "python app.py"     18 seconds ago      Up 16 seconds       80/tcp              getstartedlab_web.1.qg7mox0vrwu1ucnh6g79pnkuc
368fabab2f5b        docker-flask-demo:latest   "python app.py"     18 seconds ago      Up 15 seconds       80/tcp              getstartedlab_web.5.z01zvjtneg3rj8f5lsi9kzkwn
b34a7b9f73e6        docker-flask-demo:latest   "python app.py"     19 seconds ago      Up 17 seconds       80/tcp              getstartedlab_web.2.n7kb3qedrryxx3odog4t47hzq
746425e5bc36        docker-flask-demo:latest   "python app.py"     19 seconds ago      Up 17 seconds       80/tcp              getstartedlab_web.3.04tr7rp7euetg182oe43p6j4k
887874b4edab        docker-flask-demo:latest   "python app.py"     19 seconds ago      Up 16 seconds       80/tcp              getstartedlab_web.4.z7yh0tvvrpwju15zqwbgic1gx

集群操作app

你可以批量的更改这些容器的参数,更改docker-compose.yml中的参数后,执行docker stack deploy命令

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

Updating service getstartedlab_web (id: n94rdcq09p07hro5sqh1tjhou)
image docker-flask-demo:latest could not be accessed on a registry to record
its digest. Each node will access docker-flask-demo:latest independently,
possibly leading to different nodes running different
versions of the image.

docker将会自动帮我们更新配置,我们不需要杀死容器,

如果我们不需要这个app了,我们可以使用docker stack rm删除

$ docker stack rm getstartedlab

Removing service getstartedlab_web
Removing network getstartedlab_webnet

这将删除getstartedlabapp,但是节点群仍然存在,并且仍然在运行

相关常用命令

docker stack ls              # List all running applications on this Docker host
docker stack deploy -c <composefile> <appname>  # Run the specified Compose file
docker stack services <appname>       # List the services associated with an app
docker stack ps <appname>   # List the running containers associated with an app
docker stack rm <appname>                             # Tear down an application

集群

设置你的集群

首先我们需要安装一下virtualboxdocker-machine

  • 安装docker-machine到linux
$ curl -L https://github.com/docker/machine/releases/download/v0.12.2/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
  • 安装docker-machine,不然会没有virtualbox驱动
    自行浏览virtualbox网站下载

创建一组虚拟机使用docker-machine,使用VirtualBox驱动

$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2

创建好了使用docker-machine ls命令查看一下虚拟机

$ docker-machine ls

NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.101:2376           v17.06.1-ce   
myvm2   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.06.1-ce   

打开系统中的virtualbox也能看到正在运行两个虚拟机,分别名为myvm1myvm2

virtualbox中查看虚拟机

接下来,我们应该发送命令到您的虚拟机myvm1,使其作为成为一个群组管理,发送命令使用docker-machine ssh,设置群组管理的命令为docker swarm init,所以最后的命令应该为:

$ docker-machine ssh myvm1 "docker swarm init"

注:一般都会遇到以下问题,如果遇到了请使用以下方法解决

Error response from daemon: could not choose an IP address to advertise since this system has multiple addresses on different interfaces (10.0.2.15 on eth0 and 192.168.99.101 on eth1) - specify one with --advertise-addr exit status 1

  • 使用docker-machine ls查看虚拟主机信息,记住myvm1的ip地址
  • 重新使用docker-machine ssh运行docker swarm init命令,并使用该ip地址和端口连接
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.101:2376"

Swarm initialized: current node (rgo0wk88oxw0sx2iynnfrq7ni) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-0kkgpn8xkux6fr6e3fyqg3414vrkh9x73ho1tjiljtw201d6dj-2p65t277az7rj8yg5idss1i1q 192.168.99.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

注:末尾端口一定是2377,刚开始我想当然以为是不是我的环境不一样,查看了虚拟机的ip是2376,创建集群管理是可以成功的,但是其他结点加入集群就会失败。注意:

  • 端口2377
  • 端口2377
  • 端口2377,重要的事情说三遍

看到输出如上,就是成功了。表示我们已经在虚拟机myvm1创建了一个集群,并设置为管理

可以看到,响应docker swarm init包含一个预先配置的 docker swarm join命令,您可以在要添加的任何节点上运行。复制此命令,并将其发送到myvm2 docker-machine sshmyvm2 加入您的新群组作为工作人员:

$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-0kkgpn8xkux6fr6e3fyqg3414vrkh9x73ho1tjiljtw201d6dj-2p65t277az7rj8yg5idss1i1q 192.168.99.101:2377"


This node joined a swarm as a worker.

这样就创建好了一个集群

接下来,我们可以在myvm1上使用docker node ls命令查看结点,首先我们需要使用docker-macheine ssh命令登录myvm1虚拟机

$ docker-macheine ssh

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 17.06.1-ce, build HEAD : 80114bc - Fri Aug 18 17:58:04 UTC 2017
Docker version 17.06.1-ce, build 874a737
docker@myvm1:~$ 

然后在虚拟机myvm1中执行docker node ls命令查看结点

docker@myvm1:~$ docker node ls

ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
0b7ae42ny8506cwe2rvt3sxqy     myvm2               Ready               Active              
26kzc37prtj7vlgk7tmc4lq5y *   myvm1               Ready               Active              Leader

退出虚拟机的终端只需要执行exit即可

docker@myvm1:~$ exit

如果不想直接进入虚拟机输入指定在退出呢,可以直接使用docker-machine ssh "你的命令",这样也是可以的

在集群上部署app

使用scp命令将docker-compose.yml复制到集群管理虚拟机myvm1的主目录中

$ docker-machine scp docker-compose.yml myvm1:~

在集群管理虚拟机myvm1中在集群中部署你的app,使用docker stack deploy -c docker-compose.yml getstartedlab命令

$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"

然后就会自动部署你的应用在myvm1myvm2上了。

我们可以在myvm1上查看容器运行的情况

$docker@myvm1:~$ docker stack ps getstartedlab


ID                  NAME                  IMAGE                                                                 NODE                DESIRED STATE       CURRENT STATE              ERROR               PORTS
2d0nk6cdzk9s        getstartedlab_web.1   registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1   myvm2               Running             Preparing 59 seconds ago                       
0k5x3z8kzy3c        getstartedlab_web.2   registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1   myvm1               Running             Running 58 seconds ago                         
741qhp1gjrd0        getstartedlab_web.3   registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1   myvm2               Running             Preparing 59 seconds ago                       
xar5o0a86xqd        getstartedlab_web.4   registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1   myvm1               Running             Running 58 seconds ago                         
uondlmb3agae        getstartedlab_web.5   registry.cn-hangzhou.aliyuncs.com/earthchen/docker-flask-demo:part1   myvm2               Running             Preparing 59 seconds ago  

可以看到容器分布在两个虚拟机上。

注:如果你要使用集群,那各集群主机必须开放以下指定端口

  • 端口7946用于容器网络发现的TCP / UDP。
  • 端口4789 UDP用于容器入口网络

如果你要更改你的应用,你可以更改集群管理虚拟机myvm1中的docker-compose.yml,或者更改代码。
在这些情况下,只需要在myvm1中执行docker stack deploy再次部署即可
如果有新机器需要加入集群,只需要使用docker swarm join加入该集群即可

如何离开集群

  • 如果非管理机要离开集群,只需要执行docker-machine ssh myvm2 "docker swarm leave"
  • 如果是管理机,那需要强制执行,离开集群后也会同时删除该集群docker-machine ssh myvm1 "docker swarm leave --force"

注:

  • ddocker Version: 17.05.0-ce
  • docker-machine version 0.12.2, build 9371605
  • 上述环境在ubuntu16.04 lts中搭建测试成功
  • 上述文字皆为个人看法,如有错误或建议请及时联系我

相关文章

网友评论

      本文标题:Docker学习笔记

      本文链接:https://www.haomeiwen.com/subject/gmhrdxtx.html