Docker入门教程

Docker入门教程

本教程讲述了基本的Docker使用以及踩的坑,一共包括下面几个部分

  • ubuntu14.04 64位安装Docker

  • 以Docker的方式构建应用

  • 使用Swarm集群管理

  • 使用docker-compose.yml部署集群

Ubuntu14.04 64位安装Docker

1.卸载老版本

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

老版本的Docker叫做docker、docker-engine或docker.io,现在社区版的Docker包名是docker-ce。

Docker官网上只提供了64位安装包,说不支持64位的安装,但是在网上看到有人说自己用源代码编译可以支持32位。

2.使用AUFS则安装linux-image-extra-*

为了让Docker使用Aufs,则需要安装linux-image-extra-*软件包。

sudo apt-get update
sudo apt-get install \
    linux-image-extra-$(uname -r) \
    linux-image-extra-virtual

使用apt-get update前,请先将source换为中国的源,我使用的是阿里的源,不然从ubuntu官网更新太慢。

Docker使用AUFS做什么,参考链接https://www.cnblogs.com/sammyliu/p/5931383.html

3.安装Docker CE

  1. 安装依赖包
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

2.添加Docker官方GPG key以便后续在source.list中添加source

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

apt-key add 命令用于添加一个新的key为信任key,如果key来源于标准输入,则add后面加-,如果来源于文件则add后加文件名。

3.使用下面的命令在source.list中添加Docker stable版本的source

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

4.由于添加了一个软件包下载地址,所以需要再次更新,以确保软件包列表是最新的

sudo apt-get update

5.安装docker-ce

sudo apt-get install docker-ce

6.运行Dokcer,测试是否安装成功

sudo docker run hello-world

7.解决每次都需要输入sudo,将当前用户加入docker组

sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp docker

注意:newgrp docker 是在当前shell的子shell中完成的,退出shell后,如果再使用docker需要重新切换为docker用户组。

Ubuntu安装Docker官方参考文档 https://docs.docker.com/install/linux/docker-ce/ubuntu/

以Docker的方式构建应用

过去,如果要开始编写 Python 应用,您的第一项业务是将 Python 运行时安装到机器上。但是,这会导致机器上的环境必须如此,才能使应用按预期运行;对于运行应用的服务器来说,也同样如此。
借助 Docker,您只需将可移植的 Python 运行时抓取为镜像,而无需进行安装。然后,您的构建可以将基本 Python 镜像与应用代码包含在一起,从而确保应用、其依赖项及运行时都一起提供。——原文地址 https://docs.docker-cn.com/get-started/part2

1.使用Dockerfile定义容器

Dockerfile文件会定义容器中执行的操作。

# 将官方仓库Python中tag为2.7-slim的镜像环境运行时用作父镜像 
# 其他环境均可以在https://hub.docker.com/中查找
FROM python:2.7-slim

# 将工作目录设置为 /app
# WORKDIR用来设置在Dockerfile文件中接下来的RUN,CMD,ENTRYPOINT,COPY
# 和ADD等指令的工作目录。如果不存在,将会被创建,即使以后的Dockerfile指令都不使用
WORKDIR /app

# 将当前目录内容复制到位于 /app 中的容器中
COPY . /app

# 安装 requirements.txt 中指定的任何所需软件包
RUN pip install -r requirements.txt

# 使端口 80 可供此容器外的环境使用
EXPOSE 80

# 定义环境变量
ENV NAME World

# 在容器启动时运行 app.py
CMD ["python", "app.py"]

requirements.txt文件内容如下:

Flask
Redis

app.py文件内容如下:

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

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)

2.构建应用

在该目录ls应该显示出下面三个文件

ls
app.py  Dockerfile  requirements.txt

运行docker build构建命令,这个命令会创建Docker镜像,使用-t 可以对该镜像进行命名格式如下repository:tag,不写tag则默认为latest。

docker build -t myimage:v1.0 .

构建完成后,可以通过docker images 查看本地仓库中的镜像

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myimage             v1.0                e175395fd141        11 seconds ago      149MB
python              2.7-slim            4fd30fc83117        7 weeks ago         138MB
hello-world         latest              f2a91732366c        2 months ago        1.85kB

3.运行应用

使用-p来将机器的4000端口映射到容器暴露的80端口,即可通过机器的4000端口来访问容器内跑的web服务。

docker run -p 4000:80 myimage:v1.0

通过docker ps 来查看容器ID ,通过docker stop ID 来停止这个容器

4.共享镜像

镜像库是镜像仓库的集合,而镜像仓库是镜像的集合,类似于 GitHub 镜像仓库。镜像库中的一个帐户可以创建很多镜像仓库。默认情况下,docker CLI 使用 Docker 的公用镜像库。
1.使用Docker ID登陆
如果您没有 Docker 帐户,请在 cloud.docker.com 中进行注册。记录您的用户名。

虽然cloud.docker.com没有被墙,但是该网站使用了google的验证码,所以注册账号需要翻墙~无奈。

docker login

2.标记镜像及发布
使用docker tag命令将本地镜像与镜像库中的镜像仓库相关联的表示法为 username/repository:tag

# 按照关联的格式将本地镜像重新打一个tag
docker tag myimage:v1.0 382906025/myimage
# 将该镜像push到镜像库 也就是发布镜像
docker push 382906025/myimage

使用docker-compose.yml文件构建集群服务

docker-compose.yml 文件是一个 YAML 文件,用于定义 Docker 容器在生产中的行为方式。

  1. YAML格式每个冒号后面如果要跟值的话,都要先有个空格。
  2. 对于缩进空格也有严格的要求,最外层没有空格。

1.docker-compose.yml

version: "3"
services:
  web:
    # 将 username/repo:tag 替换为您的名称和镜像详细信息
    image: 382906025/myimage
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
      - webnet
networks:
  webnet:

此 docker-compose.yml 文件会告诉 Docker 执行以下操作:

  • 从镜像库中拉取我们在上个步骤上传的镜像。

  • 将该镜像的五个实例作为服务 web 运行,并将每个实例限制为最多使用 10% 的 CPU(在所有核心中)以及 50MB RAM。

  • 如果某个容器发生故障,立即重启容器。

  • 将主机上的端口 80 映射到 web 的端口 80。

  • 指示 web 容器通过负载均衡的网络 webnet 共享端口 80。(在内部,容器自身将在临时端口发布到 web 的端口 80。)

  • 使用默认设置定义 webnet 网络(此为负载均衡的 overlay 网络)。

2.运行swarm集群

运行下面命令,使得该Docker作为集群节点的leader

 docker swarm init --advertise-addr 10.211.55.6:2377

—advertise-addr参数是当主机中有多个网卡对应多个IP,docker不知道使用哪个ip发布时必须设置的参数。

部署集群应用

docker stack deploy -c docker-compose.yml dockerdemo

运行此命令。必须为应用指定一个名称。在此处该名称设置为 dockerdemo

# 使用docker stack ps + 集群名称 查看刚才启动的集群
docker stack ps dockerdemo
ID                  NAME                IMAGE                      NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
tolss7y1iemg        dockerdemo_web.1    382906025/myimage:latest   ubuntu              Running             Running 5 minutes ago                       
mm4zyd1s0yrb        dockerdemo_web.2    382906025/myimage:latest   ubuntu              Running             Running 5 minutes ago                       
ockncbvd6ots        dockerdemo_web.3    382906025/myimage:latest   ubuntu              Running             Running 5 minutes ago                       
vlw7errx6x50        dockerdemo_web.4    382906025/myimage:latest   ubuntu              Running             Running 5 minutes ago                       
ikhlpmv0v0w2        dockerdemo_web.5    382906025/myimage:latest   ubuntu              Running             Running 5 minutes ago       

使用docker swarm leave停止并退出集群

docker swarm leave --force

当节点是leader时退出该集群,则需要加上 –force参数

使用 docker stack rm 清除应用

docker stack rm dockerdemo

使用Swarm技术管理多台物理机集群

swarm 是一组运行 Docker 并且已加入集群中的机器。执行此操作后,您可以继续运行已使用的 Docker 命令,但现在它们在集群上由 swarm 管理节点执行。 swarm 中的机器可以为物理或虚拟机。加入 swarm 后,可以将它们称为节点。

WARNING:
刚开始使用的Mac电脑搭建Docker Swarm 集群,后来发现Mac电脑使用docker swarm init 命令后,无法在自己电脑上开启2377端口,google找到mac电脑上同样的问题,但是没有解决,所以采用Mac电脑上装了PD虚拟机,然后使用PD虚拟机模拟两台Ubuntu14.04 64位电脑进行模拟物理机管理。

使用docker swarm init 命令将一个Docker作为swarm集群的leader。看提示就可以知道如何把其他Docker机器加入到该Swarm集群中。

$ docker swarm init --advertise-addr 10.211.55.6:2377
Swarm initialized: current node (sproqls2dt9qcpore6vr8tjkr) is now a manager.

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

    docker swarm join --token SWMTKN-1-6dbou7kya21vrvin6qf0zulblrgj3q3qoc8o9isml2lmlfjix9-17dmvbyaukts8nvwlad6ucbsz 10.211.55.6:2377

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

在另一台Ubuntu14.04 64位的机器上运行命令:

docker swarm join --token SWMTKN-1-6dbou7kya21vrvin6qf0zulblrgj3q3qoc8o9isml2lmlfjix9-17dmvbyaukts8nvwlad6ucbsz 10.211.55.6:2377

然后回到leader机器,查看当前集群中机器节点,运行命令:

docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
cw5shd4skqnfe8bysiuzcg0st     ubuntu              Ready               Active              
sproqls2dt9qcpore6vr8tjkr *   ubuntu              Ready               Active              Leader

发现已经两条记录了,虽然主机名字都是ubuntu,是因为我使用的PD虚拟机直接克隆了两台虚拟机,导致了名字一样。

以后管理两台机器,只需要在leader机器上执行部署docker-compose.yml文件就可以了,五个容器自动实现负载均衡。

$ docker stack deploy -c docker-compose.yml dockerdemo
Creating network dockerdemo_webnet
Creating service dockerdemo_web
$ docker stack ps dockerdemo
ID                  NAME                IMAGE                      NODE                DESIRED STATE       CURRENT STATE              ERROR               PORTS
525xh2sjz0rf        dockerdemo_web.1    382906025/myimage:latest   ubuntu              Running             Preparing 15 seconds ago                       
5skz20pyz2f7        dockerdemo_web.2    382906025/myimage:latest   ubuntu              Running             Running 12 seconds ago                         
mhhxi4retzn0        dockerdemo_web.3    382906025/myimage:latest   ubuntu              Running             Preparing 15 seconds ago                       
v9yfeyfvf82v        dockerdemo_web.4    382906025/myimage:latest   ubuntu              Running             Running 12 seconds ago                         
l73obktgqxso        dockerdemo_web.5    382906025/myimage:latest   ubuntu              Running             Running 12 seconds ago  

集群中添加多个服务

  • web应用

  • 可视化监控

  • redis应用

完整的docker-compose.yml如下

version: "3"
services:
   web:
     # 将 username/repo:tag 替换为您的名称和镜像详细信息
     image: 382906025/myimage
     deploy:
       replicas: 5
       restart_policy:
         condition: on-failure
       resources:
         limits:
           cpus: "0.1"
           memory: 50M
     ports:
       - "80:80"
     networks:
       - webnet
   visualizer:
     image: dockersamples/visualizer:stable
     ports:
       - "8080:8080"
     volumes:
       - "/var/run/docker.sock:/var/run/docker.sock"
     deploy:
       placement:
         constraints: [node.role == manager]
     networks:
       - webnet
   redis:
     image: redis
     ports:
       - "6379:6379"
     volumes:
       - ./data:/data
     deploy:
       placement:
         constraints: [node.role == manager]
     networks:
       - webnet
networks:
   webnet:

重新运行docker stack deplay命令,即可更新服务

docker stack deploy -c docker-compose.yml dockerdemo
Creating service dockerdemo_redis
Updating service dockerdemo_web (id: i4lsgr7bty9a1uye44musbvy7)
Creating service dockerdemo_visualizer
  1. 由于之前没有redis和visualizer服务,所以可以看到这两个服务是创建服务
  2. 由于web服务已经存在了,所以web服务是更新服务
  3. Docker容器中可以使用服务名相互访问,所以app.py文件中可以使用redis来访问redis服务。
  4. data目录权限的问题,我将data目录改为777时,并不能把容器中的数据写到data目录,然后使用root权限操作容器的停止,则将容器中的数据保存到了data目录,可以看出,容器中的数据写回data目录,是在容器停止时写入的。

参考链接 https://docs.docker-cn.com/get-started/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值