Ubuntu系统上安装Docker
sudo apt-get remove docker docker-engine docker.io containerd runc
安装步骤:
更新软件包索引
sudo apt-get update
安装包以允许apt通过HTTPS使用存储库:
sudo apt-get install \
apt-transport-https \
curl \
gnupg-agent \
software-properties-common
添加Docker官方GPG密匙
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
通过搜索指纹的最后8个字符,验证您现在拥有带指纹的密钥
$ sudo apt-key fingerprint 0EBFCD88
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown] Docker Release (CE deb) <[email protected]>
sub rsa4096 2017-02-22 [S]
使用以下命令设置稳定存储库。要添加nightly
或test
存储库,请在下面的命令中的单词后添加单词nightly
或test
(或两者)stable。了解夜间和测试频道.
x86_64/arm64处理器使用一下命令
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
更新apt包索引
sudo apt-get update
安装最新的docker CE 和 containerd
sudo apt-get install docker-ce docker-ce-cli containerd.io
安装特定版本的Docker CE
列出可用版本
apt-cache madison docker-ce
例如,使用版本5:18.09.1-3-0-ubuntu-xenial
sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
运行hello-word
验证是否正确安装了Docker CE
sudo docker run hello-word
此时Docker CE 已经正确安装. docker
组已经创建,但是尚未向其添加任何用户.
先运行sudo apt-get update
, 然后按要求选择版本
卸载Docker CE软件包
sudo apt-get purge docker-ce
主机上的图像,容器,卷或自定义配置文件不会自动删除。要删除所有图像,容器和卷:
sudo rm -rf /var/lib/docker
Docker守护程序绑定到Unix套接字而不是TCP端口。默认情况下,Unix套接字由用户拥有root,其他用户只能使用它sudo。Docker守护程序始终以root用户身份运行。
如果您不想在docker命令前加上sudo,请创建一个名为的Unix组docker并向其添加用户。当Docker守护程序启动时,它会创建一个可由该docker组成员访问的Unix套接字。
创建Docker组
sudo groupadd docker
将我的用户添加到Docker组
sudo usermod -aG docker $USER
注销账户重新登录
大多数的Linux发行版使用systemd
命令,Ubuntu 14.10及以下使用upstart。
sudo systemctl enable docker
如果要禁止自启动
sudo systemctl disable docker
使用一下命令卸载
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
docker images,containers,volumes,networks 保存在
/var/lib/docker/
目录中.
第一次安装之前,你需要设置Docker
存储库. 之后,你可以在存储库中安装和升级.
安装需要的包. yum-utils
提供yum-config-manager
功能, 并且存储驱动程序需要device-mapper-persistent-data
和
devicemapper
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
使用以下命令设置稳定版
存储库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
Docker CE 有三个版本:
可以设置开发版
版本库
sudo yum-config-manager --enable docker-ce-nightly
设置测试版
存储库
sudo yum-config-manager --enable docker-ce-test
可以关闭开发版
或者测试版
存储库, 使用命令: yum-config-manager --disable
.
sudo yum-config-manager --disable docker-ce-nightly
安装最新版的Docker CE
和 containerd
.
sudo yum install docker-ce docker-ce-cli containerd.io
如果安装了多个存储库
如果有多个Docker版本存储库可以使用,那么使用
yum > install
或者yum update
安装时, 系统会自动选> 择最新的版本安装. 如果要安装特定的版本, 请看步骤2.
安装特定版本的Docker
a. 列出Docker CE 的版本
yum list docker-ce --showduplicates | sort -r
b. 根据版本的包名称,安装特定版本.
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
启动Docker
sudo systemctl start docker
验证是否安装成功. 运行测试映像, hello-world
sudo docker run hello-world
此命令会下载一个测试映像.
现在Docker 已经安装完成, Docker 需要管理员权限才能运行. 如果你是非管理员用户,且不想用sudo
命令, 可以设置(Linux postinstall)[https://docs.docker.com/install/linux/linux-postinstall/]
Docker是开发人员和系统管理人员使用容器开发,部署,运行应用程序的平台. 使用Linux容器部署应用程序称为容器化.
Docker的优点:
容器是通过运行一个映像来启动.映像是一个可执行的包,它包含了所有运行一个目标程序所需要的: 代码,运行环境, 函数库, 环境变量, 配置文件.
容器是映像的一个运行实例.可以使用命令docker ps
来列出当前在运行的容器
一个容器运行在原生的Linux上并且和其他容器共享主机内核. 它运行在一个独立的进程中,并不比其他可自行程序占用更多的内存,使得容器是轻量级的.
相比之下,虚拟机通过管理程序使用虚拟通道在主机上运行一个成熟的系统. 总之,虚拟机提供了一个远超过目标程序所需要的环境资源.
见开头
参看版本信息
docker --version
查看更多详细信息
docker info
或
docker version
运行hello-word测试
docker run hello-word
列出已经下载到本地的映像
docker image ls
列出所有的容器, --all 表示包括没有运行的
docker container ls --all
## List Docker CLI commands
docker
docker container --help
## 列出Docker版本和信息
docker --version
docker version
docker info
## 执行docker映像
docker run hello-world
## 列出docker镜像
docker image ls
## 列出Docker容器(running,all,all in quiet mode)
docker container ls
docker conainer ls --all
docker conainer ls -aq
现在可以使用docker创建app.
在过去, 如果你要写一个Python程序, 你的第一个任务是安装一个Python运行环境在你的机器上. 但是, 这会使你的计算机的运行环境既要运行你的app,又要匹配你的生产环境.
使用Docker, 你可以抓取一个便携的Python运行环境作为一个映像,没有必要安装. 然后, 你的构建可以包含基础的Python运行环境作为一个映像,确保你的app的依赖,运行环境等一起工作.
Dockerfile
(使用Dockerfile
文件定义容器)Dockerfile
定义那些程序运行在你的容器内的环境上. 有权使用的资源,例如:网络接口和磁盘在环境上是虚拟化的, 它是和电脑的其他部分相隔离的, 所以需要向外界露出接口, 确定什么文件需要复制到容器环境中. 做好这些之后,你可以期待定义在Dockerfile
中的你的app的构建无论在哪里都可以有相同的运行表现.
Dockerfile
在本机计算机上创建一个空文件夹. 在该文件夹中创建一个名为Dockerfile
的文件, 将以下信息复制粘贴到改文件中.
# Use an official Python runtime as a parent image
# 使用官方的Python运行环境作为一个母映像
FROM python:2.7-slim
# Set the working directory to /app
# 设置工作目录为 /app
WORKDIR /app
# Copy the current directory contents into the container at /app
# 复制当前目录的内容到容器中的 /app
COPY . /app
# Install any needed packages specified in requirements.txt
# 安装任何在requirements.txt中指定的包
RUN pip install --trusted-host pypi.python.org -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
# 当容器启动时,运行app.py
CMD ["python", "app.py"]
Dockerfile
引用的文件 app.py
, requirements.txt
. 接下来创建他们.
创建至少两个文件requirements.txt
, app.py
,将它们和Dockerfiler
放入同一文件夹. 这便完成了我们的程序. 当上述的Dockerfile
被构建到一个映像中, app.py
和 requirements.txt
被表达, 因为Dockerfile
的COPY
命令. 并且输出文件app.py
可以通过HTTP获得,是由于 EXPOSE
命令.
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)
现在可以发现pip install -r requirements.txt
安装Flask
和Redis
Python库, 并且app输出环境变量NAME
, 同时调用输出socket.gethostname()
. 最后Redis没有运行(因为我们只安装了Python库,并不是Redis本身),我们期望尝试使用它出错并且输出错误信息.
注意: 在容器内部访问容器ID时,访问主机名称, 如同进程ID一样.
你不需要Python或者其他在requirements.txt
文件中的东西在你的系统中, 也不需要构建或者运行映像安装到你的系统中. 似乎也没有真正设置Python环境.
现在开始构建应用程序,打开上述建立的根目录.目录中的文件包括:
$ ls
Dockerfile app.py requirements.txt
运行build命令, 它将创建一个Docker映像, --tag=
将设置映像的名称.-t
是缩写.
docker build --tag=friendlyhello .
# 注意最后的一个`.`,表示当前文件夹中的所有文件
创建的镜像将会在本地计算机的Docker映像仓库.
docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
注意 标签项是lstest
, 如果要加入版本号, 完整的tag设置, --tag=friendlyhello:v0.0.1
linux用户故障排除
代理服务器设置
代理服务器可能在启动时阻塞你的web应用的连接. 如果你在代理服务器的后面, 加入一下内容在你的
Dockerfile
文件中, 使用ENV
命令
来指定你的代理服务器的host和port.# Set proxy server, replace host:port with values for your servers ENV http_proxy host:port ENV https_proxy host:port
DNS setting
DNS 的错误设置可能会产和
pip
产生错误. 你需要设置自己的DNS server地址来使pip
正常工作. 你可以更改Docker进程守护的DNS,编辑在/etc/docker/daemon.json
中的配置文件.如下:{ "dns": ["your_dns_address", "8.8.8.8"] }
上述设置中,第一是你自己的DNS server , 第二个是备用的Google DNS(在中国可以正常使用?)
保存
daemon.json
并且重启docker服务.sudo server docker restart
修复完成后尝试重置运行
build
命令
运行应用, 使用-p
命令匹配计算机的4000端口到容器的端口80
.
docker run -p 4000:80 friendlyhello
现在可以在看见Python在http://0.0.0.0:80
为你的应用提供消息. 但是该消息来着容器内部, 我们已经将容器的80端口映射到主机的4000端口, 所以在浏览器中访问http://localhost:4000
4000:80端口的重映射说明了Dockerfile
中的EXPOSE
和 publish
值在启动docker run -p
时的不同.
使用ctrl + c
来退出容器.
现在让我们在后台以分离模式运行应用程序:
docker run -d -p 4000:80 friendlyhello
此时获得容器的长ID,并且容器在后台运行. 可以使用docker container ls
命令查看 容器ID.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
使用docker container stop progressID
来停止进程.
docker container stop 1fa4ab2cf395
为了证明我们创建的容器的可移植性,上传我们构建的image并且在其他地方运行它.
注册表是仓库的集合, 仓库是映像的集合. 许多代码仓库,例如Github, 会排除已经构建的代码. 注册表上的一个账号可以创建许多仓库. docker
命令行默认使用Docker的公共注册表.
也可以选择其他的注册表,Docker Trusted Registry
注册一个Docker账号 hub.docker.com.在本地登录使用:
docker login
结合本地映像和注册表上的仓库的标记是username/repository:tag
. 这个标记是可选的, 但是推荐选择. 它的作用是给image一个版本号. 给仓库和版本号一个有意义的名字,例如get-started:part2
,它将会把映像放在get-started
仓库中并且标记它为part2
.
保存映像:
docker tag image username/repository:tag
例如:
docker tag friendlyhello gordon/get-started:part2
查看映像:
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
gordon/get-started part2 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
上传你标记的映像到仓库:
docker push username/repository:tag
完成之后登录Docker Hub.
使用docker run
命令在其他机器上运行.
docker run -p 4000:80 username/repository:tag
如果本地没有该映像, Docker将会从仓库中拉去下来.
docker run -p 4000:80 gordon/get-started:part2
Unable to find image 'gordon/get-started:part2' locally
part2: Pulling from gordon/get-started
10a267c67f42: Already exists
f68a39a6a5e4: Already exists
9beaffc0cf19: Already exists
3c1fe835fb6b: Already exists
4c9f1fa8fcb8: Already exists
ee7d8f576a14: Already exists
fbccdcced46e: Already exists
Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
Status: Downloaded newer image for gordon/get-started:part2
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
无论在哪运行docker run
命令, 它都会拉去你的映像,并且会拉去所有在requirements.txt
中的依赖文件, 并且运行你的代码. 它们将会在一个小而紧凑的包里运行, 不需要再安装额外的软件.
docker build -t friendlyhello . # 使用Dockerfile创建映像
docker run -p 4000:80 friendlyhello # Run "friendlyhello" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello # 在分离模式下运行,即在后台运行
docker container ls # 列出所有在运行的容器
docker container ls -a # 列出所有运行和不运行的容器
docker container stop <hash> # 停止指定的容器
docker container kill <hash> # 强制关闭指定容器
docker container rm <hash> # 从机器中删除指定的容器
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry
在第三部分, 规划我们的应用程序并且使其加载均衡. 为了实现它,我们要在分布式应用程序的上一层:server层.
在一个分布式的应用中, app的不同部分被称为services
. 例如, 如果你想建立一个视频分享网站, 当用户上传了一个视频之后一个转码的服务将在后台运行, 并且前端服务等程序在运行.
servives
仅仅是 containers in production
. 服务仅仅运行在一个image
上, 但是它编码了映像运行的方式:它应该运行在那些端口,应该运行多少的副本,等等. 扩展服务会增加运行程序的容器实例的数量, 会分配更多的计算机资源给服务进程.
在Docker中,定义,运行,和规划服务将会非常容易. --仅仅写一个docker-compose.yml
文件即可.
Your first docker-compose.yml
filedocker-compose.yml
是一个YAML
文件, 它定义了Docker容器在生产环境的表现.
在任何地都可以保存docker-compose.yml
文件. 确保你在第二部分已经将映像推送到注册表中, 并且通过替换username/repo:tag
来更新.yml
.
.yml
文件信息
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:
上述的 docker-compose.yml
文件告诉Docker做以下工作:
web
的服务, 限制每个实例最多占用10%的CUP使用率,和50M 内存.web
'的容器通过一个叫做webnet
的加载均衡网络共享80端口.webnet
网络使用默认设置. webnet
是一种负载均衡的覆盖网络.在我们运行docker stack deploy
命令之前, 先运行:
docker swarm init
关于
docker swarm init
的介绍将在第四部分.
现在可以运行了. 需要给你的app一个名称, 下面的命令中名称为getstartedlab
:
docker stack deploy -c docker-compose.yml getstartedlab
我们的一个服务栈将运行5个容器在我们部署的端口上.
获取服务的 ID
docker service ls
根据app的名字来寻找我们创建的web
服务. 在上面的例子中我们将其命名为getstartedlab
.
docker stack services getstartedlab
ID NAME MODE REPLICAS IMAGE PORTS
bqpve1djnk0x getstartedlab_web replicated 5/5 username/repo:tag *:4000->80/tcp
在输出中,将会看家服务的ID, 名称, 模式, 重复数量, 映像, 端口信息
运行在service中的一个容器被称为一个task
. tasks
被赋予数字上递增的唯一ID,取决于docker-compose.yml
文件中的replicas
定义的参数.
列出service中的task
s
docker service ps getstartedlab_web
如果仅仅列出所有系统中的task
,没有被服务过滤的和被服务过滤的都会被列出来.
docker container ls -q
你可以在多运行curl -4 https://localhost:4000
(如果由于报错可以试试将https改为http)几次, 或者去在浏览器中多刷新几次.
你会发现容器的ID变了, 证明负载均衡在这5个task中选择.
你可以运行docker stack ps
来查看所有的tasks. 输出如下:
docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
uwiaw67sc0eh getstartedlab_web.1 username/repo:tag docker-desktop Running Running 9 minutes ago
sk50xbhmcae7 getstartedlab_web.2 username/repo:tag docker-desktop Running Running 9 minutes ago
c4uuw5i6h02j getstartedlab_web.3 username/repo:tag docker-desktop Running Running 9 minutes ago
0dyb70ixu25s getstartedlab_web.4 username/repo:tag docker-desktop Running Running 9 minutes ago
aocrb88ap8b0 getstartedlab_web.5 username/repo:tag docker-desktop Running Running 9 minutes ago
你可以通过在docker-compose.yml
文件中修改replicas
来修改app的规模.
保存修改后,重新运行docker stack deploy
命令:
docker stack deploy -c docker-complose.yml getstartedlab
docker 进行一个现场更新, 不需要先撤销task
和kill 容器.
现在运行docker container ls -q
命令来查看部署的实例的配置信息.
使用docker stack rm
命令来拆解app:
docker stack rm getstartedlab
拆解群
docker swarm leave --force
下一个部分将学习在Docker机器集群运行你的app.
docker stack ls # List stacks or apps
docker stack deploy -c <composefile> <appname> # Run the specified Compose file
docker service ls # List running services associated with an app
docker service ps <service> # List tasks associated with an app
docker inspect <task or container> # Inspect task or container
docker container ls -q # List container IDs
docker stack rm <appname> # Tear down an application
docker swarm leave --force # Take down a single node swarm from the manager
第四部分将介绍怎样将你的应用部署到集群, 将它运行在多机器系统中.
荣通过连接多个机器到一个被称为Dockerized
的簇,使得多容器和多机器程序构成一个群集.
集群是一组计算机运行Docker并且加入到集群中. 在这之后,你可以继续运行你习惯的docker命令, 但是现在他们通过swarm manager
(集群管理器)运行在集群中. 集群中的机器可以是实际的机器也可以是虚拟机. 当加入到集群之后他们都被称为node
(节点).
集群管理器可以运用几种策略来运行容器, 例如: emptiest node
(最空节点):它用容器填充利用率最低的机器;global
(全局):它确保每个机器恰好启动一个指定容器的实例. 你可以在Compose file
中为集群管理器指定策略.
集群管理器是在一个集群中唯一一个你可以执行你的命令的机器, 或者授权背的机器加入集群作为workers
. workers
仅仅能够提供生产力并没有权限告诉其他机器自己能做什么.
到目前为止, 你只是使用Docker在你本地的一个主机上. 但是Docker的强大之处在于它可以切换到swarm mode
集群模式. 启动集群模式会立即使得当前机器称为集群管理员. 之后,Docker在集群的机器上执行你的任务,而不是只在你的当前主机上.
集群是由多节点组成, 实际的机器或是虚拟机都可以作为节点.
运行docker swarm init
来打开集群模式并使你当前机器作为集群管理员.
之后在其他机器运行docker swarm join
来使他们加入到集群中.
Docker Machine是一个工具,可让你在虚拟主机上安装Docker Engine,并使用docker-machine命令管理主机。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
首先安装虚拟机 ( install Oracle VirtualBox )[https://www.virtualbox.org/wiki/Downloads].
使用docker-machine
创建一些虚拟机:
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
现在你创建了两个虚拟机,myvm1
,myvm2
.
使用一下命令列出虚拟机的IP, 可能需要管理员权限.
docker-machine ls`
以下是输出样例:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
第一台机器作为管理员, 它执行管理命令和授权其他机器加入集群.
使用docker-machine ssh
发送命令到虚拟机.
使用docker swarm init
命令来使myvm1
成为集群管理员,输入如下:
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr "
Swarm initialized: current node <node ID> is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token <token> \
<myvm ip>:<port>
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
端口2377 和端口 2376
docker swarm init
和docker swarm join
使用>端口2377或者使用默认端口.
docker-machine ls
命令返回机器的IP地址包括端口>2376,改端口是docker守护进程的端口, 请不要使用该端>口做其他事情.使用SSH有问题? 试试
--native-ssh
标签Docker 机器可以让你使用原生ssh而不是docker集成的ssh.使用一下命令将会调用机器原生的ssh
docker-machine --native-ssh ssh myvm1 ...
docker swarm init
命令包含了预设的docker swarm join
命令, 复制它,然后在myvm2
上执行,使myvm2
作为一个工作节点加入到集群.
$ docker-machine ssh myvm2 "docker swarm join \
--token \
:2377"
This node joined a swarm as a worker.
到此,一个简单的集群创建完成.
在管理员机器上运行docker node ls
:
$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd myvm2 Ready Active
rihwohkh3ph38fhillhhb84sk * myvm1 Ready
如果想使得一个节点脱离集群, 使用命令:
docker swarm leave
.
有两点需要记住
workers
节点只能进行工作docker-machine
脚本到目前已经学习了:docker-machine ssh
命令来控制虚拟机.
另外一种方法是docker-machinne env
命令配置当前脚本并与虚拟机上的Docker守护程序进行通信. 在下一部分中该方法的效果更好,因为它允许你使用本地的docker-compose.yml
文件配置远程的app.
输入docker-machine env myvm1
, 之后复制粘贴并运行输出的最后一行提供的命令,配置shell与集群管理员通信(myvm1).
配置shell的命令根据系统不同而提供不同版本.以下只研究Linux版本
运行docker-machine env myvm1
来获取一条命令,该命令用于配置你的的shell与myvm1
进行通信.
$ 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)
运行docker-machine ls
来查看mymv1
是否在运行, *
表示激活作态.
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
现在myvm1
已经启动, 可以使用它作为集群管理员使用docker stack deploy
命令和docker-compose.yml
文件来配置你的app,
在集群管理员上使用docker service ps
命令确认所有的服务被重新部署.
确保当前终端路径中包含docker-compose.yml
文件. 运行以下命令:
docker stack deploy -c docker-compose.yml getstartedlab
现在,app已经成功部署到了集群上.
如果你的
image
是存储在私有仓库的,那么你需要docker login
命令来登录; 另外还要 >--with-registry-auth
标志.docker login registry.example.com docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab
现在使用和第三部分相同的命令查看task
, 方向,servers
被分配在了myvm1
和myvm2
上.
$ docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE
jq2g3qp8nzwx getstartedlab_web.1 gordon/get-started:part2 myvm1 Running
88wgshobzoxl getstartedlab_web.2 gordon/get-started:part2 myvm2 Running
vbb1qbkb0o2z getstartedlab_web.3 gordon/get-started:part2 myvm2 Running
ghii74p9budx getstartedlab_web.4 gordon/get-started:part2 myvm1 Running
0prmarhavs87 getstartedlab_web.5 gordon/get-started:part2 myvm2 Running
docker-machine env
和 docker-machine ssh
来连接虚拟机.
myvm2
,仅需要再次在shell终端中运行docker-machine env
命令, 之后运行给出的命令连接myvm2
.如果你换了一个没有配置的shell或一个新的shell,你需要重新运行配置指令. 使用docker-machine ls
列出所有的机器, 查看它们的状态,IP的信息,并找出哪一个已经连接.docker-machine ssh ""
, 该方式的logs会直接记录到VM中,但是不会立即给你在本地机器上的访问通道.docker-machine scp :~
来复制文件到其他机器.你可以通过myvm1
和myvm2
的IP地址来访问你的app.
运行docker-machine ls
来获取 VMs’ IP地址并且在浏览器中访问他们.
确保集群节点上的7946和4789端口打开:
- 7946 TCP/UDP 用于容器网络发现
- 4789 UDP 用于容器入口网络
在这里可以做第二部分和第三部分的操作.
扩展app通过更在docker-compose.yml
文件.
更在app的行为,通过编辑代码,重构,并推送新的image
.
无论在什么情况下,运行docker stack deploy
来部署更改.
你可以使用docker warm join
来增加集群的节点. 在运行docker stack deploy
之后, app即可利用新的计算资源.
Stacks and swarms
你可以撤销stack
使用命令:docker stack rm
:
docker stack rm getstartedlab
保留机器或者移除
docker-machine ssh myvm2 "docker swarm leave"
docker-machine ssh myvm1 "docker swarm leave --force"
取消对docker-machine shell的变量设置
在 Mac or Linux 上:
eval $(docker-machine env -u)
在Windows系统上:
"C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression
以上命令将会断开与docker-machine
创建的虚拟机的连接.
重启
如果关闭了本地主机, Docker机器停止执行. 查看Docker机器的状态使用命令:docker-machine ls
.
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Stopped Unknown
myvm2 - virtualbox Stopped Unknown
为重启机器,运行:
docker-machine start <machine-name>
例如:
$ docker-machine start myvm1
Starting "myvm1"...
(myvm1) Check network to re-create if needed...
(myvm1) Waiting for an IP...
Machine "myvm1" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
$ docker-machine start myvm2
Starting "myvm2"...
(myvm2) Check network to re-create if needed...
(myvm2) Waiting for an IP...
Machine "myvm2" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
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 <file> <app> # 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
该部分是分布式应用程序的顶层:stack
. stack
是是一组共享依赖,可以相互协调和扩展的一组服务.
一个stack
可以定义和协调一个完整的app的功能(尽管复杂的程序可能会需要多个stack
).
一些好消息是,从第3部分开始,当您创建Compose文件并使用时,您在技术上一直在使用stack
docker stack deploy
。但这是在单个主机上运行的单个服务堆栈,不是生产环境所用device方法。在这部分,将使多个服务相互关联,并在多台计算机上运行它们。
使用docker-compose.yml
文件可以很容易的添加服务.
首先增加一个观察者服务, 用它来观察我们的集群怎么调度容器.
打开docker-compose.yml
文件, 使用一下文件替换内容.注意username/repo:tag
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
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
networks:
webnet:
这里新加入了一个名为visualizer
的web
服务.
注意这里有两个新的东西:
valumes
键: 让可视化工具访问Docker的主机套接字文件;placement
秘钥: 确保这个服务只能在swarm
管理器上运行,但不是一个worker
节点.该容器是docker开源项目创建的, 用一个图标来展示集群上运行的Docker服务.
确保shell终端与myvm1
在通信状态.
docker-machine ls
列出计算机并确保已经连接上myvm1
.*
表示连接上.docker-machine env myvm1
, 详情请看第四部分.在管理器上重新运行命令docker stack deplay
, 并更新需要更新的任何服务:
$ docker stack deploy -c docker-compose.yml getstartedlab
Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm)
Creating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)
查看可视化工具
在compose文件中设置了visualizer
的端口的8080
, 运行docker-machine ls
获取其IP地址. 然后在浏览器中查看.
现在添加Redis
数据库来存储aap的数据.
修改docker-compose.yml
文件:
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
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:
- "/home/docker/data:/data"
deploy:
placement:
constraints: [node.role == manager]
command: redis-server --appendonly yes
networks:
- webnet
networks:
webnet:
在Docker中有一个Redis
的官方映像,并拥有一个简短的映像名称:redis
. Redis默认使用容器的6379端口暴露给主机.
最重要的是,在redis
的规范中有如下几个事情会使数据在stack
的部署之间保持不变:
- `redis`总是在管理器(管理员节点)上运行,所以它总是使用相同的文件系统.
- `redis`在主机的任意文件路径下作为数据的存储路径.
总之, 它在主机的物理文件系统中为redis数据创建数据库, 否则, redis
将数据存储在容器的文件系统中, 如果重启容器,数据将会丢失.
"数据的真实来源"包含一下两个内容:
在管理员节点上创建一个./data
文件夹.
docker-machine ssh myvm1 "mkdir ./data"
myvm1
的通讯.docker-machine ls
来列出并且确认你已经连接上了myvm1
,连接上以后会有一个*
号.docker-machine env myvm1
, 该命令会给出一条命令,复杂这条命令并运行它.
eval $(docker-machine env myvm1)
在Windows系统上:"C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
再一次运行docker stack deploy
docker stack deploy -c docker-compose.yml getstartedlab
运行docker service ls
命令,来查看这三个服务已经在正确的运行.
docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
x7uij6xb4foj getstartedlab_redis replicated 1/1 redis:latest *:6379->6379/tcp
n5rvhm52ykq7 getstartedlab_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp
mifd433bti1d getstartedlab_web replicated 5/5 gordon/getstarted:latest *:80->80/tcp
在一个节点上访问:http://192.168.99.101
,查看访问者数量,现在它被Redis存储,并可以被正确访问.
另外,在任一个节点的IP加端口号8080访问Docker可视化界面,例如:192.168.99.100:8080
.可以看见正在运行的redis
服务.
本节将学习Dockerized application
的一些选项.
运行docker swarm init
来创建一个集群.
运行 docker stack deploy -c docker-compose.yml getstartedlab
命令来部署应用在云主机上.
docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web
Creating service getstartedlab_visualizer
Creating service getstartedlab_redis
以下为一些必须熟悉的命令:
docker node ls
列出集群所有节点.docker service ls
列出所有服务docker service ps
列出一个服务的所有tasks
(任务).如果app被部署到了云服务器,需要在服务器上打开几个必须的端口.因为一下几个原因:
redis
和web
服务之间通信web
的任何节点,以便web服务和visualizer
可以在浏览器中访问.manager
节点的ssh访问.以下是服务需要暴露的端口:
service | Tpye | Protocol | Port |
---|---|---|---|
web | HTTP | TCP | 80 |
visualizer | HTTP | TCP | 8080 |
redis | TCP | TCP | 6379 |
docker-compose.yml
文件并且使用命令docker stack deploy
重新部署docker stack rm
.例如:docker stack rm getstartedlab
现在我以及学习完docker的使用,以下为进一步学习内容:
docker默认的存储位置为/val/lib/docker
更改存储位置
docker save -o 文件名.tar 镜像名
sudo mkdir /etc/systemd/system/docker.service.d
sudo touch /etc/systemd/system/docker.service.d/docker-overlay.conf #文件名应该可以随便取
sudo vim /etc/systemd/system/docker.service.d/docker-overlay.conf
sudo systemctl daemon-reload
sudo systemctl restart docker
docker load -i [docker备份文件.tar]
/var/lib/docker
目录sudo rm -r /var/lib/docker