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
- 安装依赖包
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 容器在生产中的行为方式。
- YAML格式每个冒号后面如果要跟值的话,都要先有个空格。
- 对于缩进空格也有严格的要求,最外层没有空格。
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
- 由于之前没有redis和visualizer服务,所以可以看到这两个服务是创建服务
- 由于web服务已经存在了,所以web服务是更新服务
- Docker容器中可以使用服务名相互访问,所以app.py文件中可以使用redis来访问redis服务。
- data目录权限的问题,我将data目录改为777时,并不能把容器中的数据写到data目录,然后使用root权限操作容器的停止,则将容器中的数据保存到了data目录,可以看出,容器中的数据写回data目录,是在容器停止时写入的。