linux项目部署学习(5) - docker
7.docker
yaml配置文件
你用过哪些配置文件?
不同的配置文件,遵循的语法也不一样
-
json
-
conf -- nginx.conf ; my.conf
-
ini -- uwsgi.ini
-
xml -- xml格式的配置文件
-
yaml -新式配置文件,用在docker/salt/ansible/k8s等配置文件中,遵循python的缩进语法
-
语法规则 大小写敏感 使用缩进表示层级关系 缩进时禁止tab键,只能空格 缩进的空格数不重要,相同层级的元素左侧对其即可 # 表示注释行 yaml支持的数据结构 对象: 键值对,也称作映射 mapping 哈希hashes 相当于python中字典 dict 冒号表示 key: value key冒号后必须有 数组: 一组按次序排列的值,又称为序列sequence 相当于 python中的列表list 短横线 - list1 纯量: 单个不可再分的值 ##对象:键值对 yaml first_key: second_key:second_value python { 'first_key':{ 'second_key':'second_value', } }
-
在线解析地址:http://old.qqe2.com/jsontool/yaml.php
docker容器三大基本概念
镜像 image
容器 container
仓库 repository
docker整个生命周期就是这三个概念。
docker镜像
Docker镜像就是一个只读的模板。
例如:一个镜像可以包含一个完整的CentOS操作系统环境,里面仅安装了Apache或用户需要的其他应用程序。
镜像可以用来创建Docker容器。
Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
image的分层存储
因为镜像包含完整的root文件系统,体积是非常庞大的,因此docker在设计时按照Union FS的技术,将其设计为分层存储的架构。镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成。
docker容器(container)
image和container的关系,就像面向对象程序设计中的 类和实例一样,镜像是静态的定义(class),容器是镜像运行时的实体(object)。
容器可以被创建、启动、停止、删除、暂停
Docker利用容器来运行应用。
容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
docker仓库(repository)
仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快读的访问。
当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下载在另外一台机器上使用这个镜像时候,只需需要从仓库上pull下来就可以了。
注意:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。
docker Registry
Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服 务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务 供用户管理私有镜像。
最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并 拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相 关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像 使用的就是这个服务。
由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针 对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见 的有 阿里云加速器、DaoCloud 加速器、灵雀云加速器等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提高很多。在后 面的章节中会有进一步如何配置加速器的讲解。
国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓 库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。
安装 docker
系统环境准备
docker最低支持centos7且在64位平台上,内核版本在3.10以上
[root@oldboy_python ~ 10:48:11]#uname -r
3.10.0-693.el7.x86_64
参考:https://www.cnblogs.com/pyyu/p/6925606.html
使用阿里云。腾讯云的yum源,可以直接安装docker软件,但是版本低,如果要下载新的,需要去docker官网下载
1.yum install docker -y
2.配置docker的镜像加速器(国内源下载镜像速度快,默认是去国外下载)
#一条命令加速
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://95822026.m.daocloud.io
#这里有一个bug,需要修改docker的配置文件,删除json结尾的逗号。
vi /etc/docker/daemon.json
{"registry-mirrors": ["http://95822026.m.daocloud.io"]}
或者直接 vi /etc/docker/daemon.json
{"registry-mirrors": ["https://dockerhub.azk8s.cn","https://hub-mirror.c.163.com"]}
3.systemctl restart docker #重启docker
4.获取一个centos基础镜像,docker的系统镜像非常小,centos只有200m
docker pull centos
启动docker
systemctl start docker #启动docker
systemctl restart docker #重启docker
systemctl enable docker #开机启动docker
systemctl status docker #查看docker状态
docker命令
增
1.从dockerhub,仓库去获取docker的镜像,从github获取代码一个意思。
docker pull centos #从docker仓库去找
docker pull ubuntu
删
1.删除本地镜像文件
docker rmi 镜像name/id #删除镜像id的前3位即可
2.删除容器记录的命令(已经挂掉的进程)
docker rm 容器id
docker rm -f 容器id 强制杀死
3.批量清空无用的docker容器记录,容器
docker rm `docker ps -aq`
4.批量删除镜像(危险操作,谨慎啊兄弟)
docker rmi `docker images -aq`
改(启动)
1.运行一个docker容器,运行镜像文件,产生容器进程
docker run 镜像文件名即可
docker run centos #如果docker容器中没有在运行的进程,容器会直接挂掉。
docker run指定还有一个功能,当镜像不存在的时候,会自动下下载该进程。
#如果你发现你的容器没有启动成功,说明容器内部出错,程序没有运行
2.交互式的运行一个存活的docker容器
#-it参数 -i是交互式的命令操作 -t开启一个终端 /bin/bash指定shell解释器
docker run -it centos /bin/bash #此时进入docker容器内部
3.运行一个活着的容器后台运行
docker run
-d 时让容器后台运行
-c 指定一段shell代码
--name 给容器起个名字好管理 (写道最前面)
docker run -d centos /bin/bash -c "while true;do echo 靓仔;sleep 1;done"
docker run --name "指定容器的名字" -d centos /bin/bash -c "while true;do echo 靓仔;sleep 1;done"
5.启动/停止容器
docker stop c02
docker start c02
docker restart c02 重启容器
6.进入一个正在运行的容器
docker exec -it 容器id /bin/bash
7.进入容器,修改代码(写程序),提交,发给其他人安装。
7.1
docker run -it docker.io/centos /bin/bash
yum install vim -y
7.2 exit
7.3 提交容器生成新的镜像文件
docker commit bd42e16f4763 s_vim_centos
#此时docker images 就有你打的镜像了
[root@VM-0-6-centos docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
s_vim_centos latest 9939e36540ed 4 seconds ago 272 MB
8.导出你的docker镜像,发给同事
#官方文档解释,docekr save 用的tar命令压缩
docker save 9939e36540ed > /opt/s_vim_centos.tar.gz
9.如何进行docker镜像导入
#在本地机器演示:
#先删除本地的s_vim_centos
# docker rmi 9939e36540ed
导入同事给的镜像
docker load < /opt/s_vim_centos.tar.gz
[root@VM-0-6-centos opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 9939e36540ed 7 minutes ago 272 MB
#首次导入该镜像发现,丢失了镜像名,重新赋予即可
docker tag 9939e36540ed s_vim_centos #打标签名字
[root@VM-0-6-centos opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
s_vim_centos latest 9939e36540ed 10 minutes ago 272 MB
10.如何在docker内,运行一个python web程序。需要用到端口映射
-d 后台运行
-P 大写的P参数,作用是随机的端口映射
-p 指定端口 -p 80:5000 #访问linux宿主机的80,就访问到docker容器的5000端口
# traning/webapp 是镜像的名字,没有会去下载
#python app.py 代表启动容器后执行python app.py
docker run -d -P training/webapp python app.py
[root@VM-0-6-centos opt]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ea99a093baf training/webapp "python app.py" 6 minutes ago Up 6 minutes 0.0.0.0:32768->5000/tcp sleepy_carson
此时在游览器访问ip:32768 就能看到界面hello world
(如果访问失败的话,检查自己的防火墙,以及云服务器的安全组)
11. 查看端口映射关系
docker port 容器id
[root@VM-0-6-centos opt]# docker port 2ea99a093baf
5000/tcp -> 0.0.0.0:32768
12.查看容器内的进程
[root@VM-0-6-centos opt]# docker top 2ea99a093baf
UID PID PPID C STIME TTY TIME CMD
root 16244 16228 0 16:00 ? 00:00:00 python app.py
docker的端口映射概念
查
1.查看本地机器的所有镜像文件内容
docker images
2.搜寻一下有哪些公有镜像
docker search centos #去仓库查看所有centos镜像,可供下载
3.查看docker正在运行的进程
docker ps #查看运行中的进程
docker ps -a #查看所有进程包括已经挂了的
4.查看容器内的标准输出
docker logs 容器id
docker logs -f 容器id #tail -f 监控日志
docker应用
当你想快速使用tornado框架,开发一些东西,你需要在物理机上
- 编译安装python3
- 安装 tornado模块以及依赖关系
- 加上你的代码才能运行
但是在docker中
docker search tornado #直接搜索,是其他人做好的镜像,里面安装好了python3和所需的依赖关系
docker pull tornado #直接下载该镜像,和代码结合使用,docker解决了你配置环境的烦恼
比如你想用nginx,又不想改变宿主主机的环境,可以直接用docker安装
docker serach nginx
docker pull nginx
docker run nginx #nginx运行在容器中,然后和宿主主机有一个端口映射就可以了访问了
dockerfile
镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础。我们之前的例子都是使用来自docker hub的镜像,直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。
镜像的定制就是定制每一层所添加的配置、文件。如果可以吧每一层修改、安装、构建、操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是dockerfile。Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令 构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
#FROM 指令表示,告诉该dockerfile以哪个镜像为基础
#比如你的技术老大,要求你们的程序运行在centos,ubuntu
FROM scratch #制作base image 基础镜像,尽量使用官方的image作为base image
FROM centos #使用base image
FROM ubuntu:14.04 #带有tag的base image
#LABEL标签,定义变量,定义作者信息,邮箱等
LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
LABEL maintainer=“yc_uuu@163.com"
#RUN 是一个完成指令,你可以用他在docker中执行任意的命令
#对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
RUN yum update && yum install -y vim \
Python-dev #反斜线换行
RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”
WORKDIR /root #相当于linux的cd命令,改变容器内的目录,尽量使用绝对路径!!!不要用RUN cd
WORKDIR /test #如果没有就自动创建
WORKDIR demo #再进入demo文件夹
RUN pwd #打印结果应该是/test/demo
#ADD指令用于把宿主机的文件,添加到容器空间内,宿主机有自己的文件系统,容器内部也有
#ADD还有一个人解压缩的功能,是个坑,需要注意
ADD and COPY #两个指令
ADD hello / #把本地文件添加到镜像中,把本地的hello可执行文件拷贝到镜像的/目录
ADD test.tar.gz / #添加到根目录并解压
WORKDIR /root
ADD hello test/ #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
COPY hello test/ #等同于上述ADD效果
ADD与COPY
- 优先使用COPY命令
-ADD除了COPY功能还有解压功能
添加远程文件/目录使用curl或wget
ENV #环境变量,尽可能使用ENV增加可维护性
ENV MYSQL_VERSION 5.6 #设置一个mysql常量
RUN yum install -y mysql-server=“${MYSQL_VERSION}”
------这里需要稍微理解一下了-------中级知识---先不讲
VOLUME and EXPOSE
存储和网络
RUN and CMD and ENTRYPOINT
RUN:执行命令并创建新的Image Layer
CMD:设置容器启动后默认执行的命令和参数
ENTRYPOINT:设置容器启动时运行的命令
Shell格式和Exec格式
RUN yum install -y vim
CMD echo ”hello docker”
ENTRYPOINT echo “hello docker”
Exec格式
RUN [“apt-get”,”install”,”-y”,”vim”]
CMD [“/bin/echo”,”hello docker”]
ENTRYPOINT [“/bin/echo”,”hello docker”]
通过shell格式去运行命令,会读取$name指令,而exec格式是仅仅的执行一个命令,而不是shell指令
cat Dockerfile
FROM centos
ENV name Docker
ENTRYPOINT [“/bin/echo”,”hello $name”]#这个仅仅是执行echo命令,读取不了shell变量
ENTRYPOINT [“/bin/bash”,”-c”,”echo hello $name"]
CMD
容器启动时默认执行的命令
如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略
如果定义多个CMD,只有最后一个执行
ENTRYPOINT
让容器以应用程序或服务形式运行
不会被忽略,一定会执行
最佳实践:写一个shell脚本作为entrypoint
COPY docker-entrypoint.sh /usr/local/bin
ENTRYPOINT [“docker-entrypoint.sh]
EXPOSE 27017
CMD [“mongod”]
[root@master home]# more Dockerfile
FROm centos
ENV name Docker
#CMD ["/bin/bash","-c","echo hello $name"]
ENTRYPOINT ["/bin/bash","-c","echo hello $name”]
发布docker image到仓库
第一种,docker hub公有镜像发布
1.docker提供了一个类似于github的仓库dockerhub,
网址https://hub.docker.com/需要注册使用
2.注册docker id后,在linux中登录dockerhub
docker login
注意要保证image的tag是账户名,如果镜像名字不对,需要改一下tag
docker tag 镜像id dockerhub账号/centos-vim
语法是: docker tag 镜像id dockerhub账号/名字
3.推送docker image到dockerhub
docker push dockerhub账号/centps-cmd-exec:latest
4.在dockerhub中检查镜像
https://hub.docker.com/
5.删除本地镜像,测试下载pull 镜像文件
docker pull yuchao163/centos-entrypoint-exec
私有仓库
但是第一种镜像仓库是公开的,其他人也是可以下载,并不安全,因此还可以使用docker registry官方提供的私有仓库
1.官方提供的私有仓库docker registry用法
https://yeasy.gitbooks.io/docker_practice/repository/registry.html
2.一条命令下载registry镜像并且启动私有仓库容器
私有仓库会被创建在容器的/var/lib/registry下,因此通过-v参数将镜像文件存储到本地的/opt/data/registry下
端口映射容器中的5000端口到宿主机的5000端口
docker run -d \
-p 5000:5000 \
-v /opt/data/registry:/var/lib/registry \
registry
3.检查启动的registry容器
docker ps
4.测试连接容器
telnet 192.168.119.10 5000
5.修改镜像tag,以docker registry的地址端口开头
docker tag hello-world:latest 192.168.119.10:5000/hello-world:latest
6.查看docker镜像,找到registry的镜像
docker images
7.Docker 默认不允许非 HTTPS 方式推送镜像。我们可以通过 Docker 的配置选项来取消这个限制,这里必须写正确json数据
[root@master /]# cat /etc/docker/daemon.json
{"registry-mirrors": ["http://95822026.m.daocloud.io"],
"insecure-registries":["192.168.119.10:5000"]
}
写入到docker服务中,写入到[Service]配置块中,加载此配置文件
[root@master home]# grep 'EnvironmentFile=/etc/docker/daemon.json' /lib/systemd/system/docker.service
EnvironmentFile=-/etc/docker/daemon.json
8.修改了docker配置文件,重新加载docker
systemctl daemon-reload
9.重启docker
systemctl restart docker
10.重启了docker,刚才的registry容器进程挂掉了,因此重新启动它
docker run --privileged=true -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry
--privileged=true docker容器的安全机制:设置特权级运行的容器
11.推送本地镜像
docker push 192.168.119.10:5000/hello-world
12.由于docker registry没有web节目,但是提供了API数据
官网教程:https://docs.docker.com/registry/spec/api/#listing-repositories
curl http://192.168.119.10:5000/v2/_catalog
或者浏览器访问http://192.168.119.10:5000/v2/_catalog13.删除本地镜像,从私有仓库中下载docker pull 192.168.119.10:5000/hello-world
打包flask程序与dockerfile
确保app.py和dockerfile在同一个目录!
1.准备好app.py的flask程序
[root@master home]# cat app.py
#coding:utf8
from flask import Flask
app=Flask(__name__)
@app.route('/')
def hello():
return "hello docker"
if __name__=="__main__":
app.run(host='0.0.0.0',port=8080)
[root@VM-0-6-centos s_docker]# ls
app.py Dockerfile
2.在宿主主机上检查脚本是否能运行
pip3 install -i https://pypi.douban.com/simple flask
3.编写dockerfile
touch Dockerfile 必须是大写的
FROM python #指定镜像,dockerhub提供好的python镜像,已经安装好了python3
RUN pip3 install -i https://pypi.douban.com/simple flask
COPY app.py /opt/
WORKDIR /opt
EXPOSE 8080 #打开容器内的8080端口,用于和宿主主机映射
CMD ["python3","app.py"] #在容器启动后,内部自动执行的命令是什么
4.检查准备的脚本和Dockerfile文件
[root@VM-0-6-centos s_docker]# ls
app.py Dockerfile
5.构建docekr镜像,并查看改镜像名
docker build .
[root@VM-0-6-centos s_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 0f23996686c8 46 seconds ago 943 MB
[root@VM-0-6-centos s_docker]# docker tag 0f23996686c8 s_flask
[root@VM-0-6-centos s_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
s_flask latest 0f23996686c8 3 minutes ago 943 MB
6.指定宿主主机端口8070,映射容器内的端口8080
docker run -d -p 8070:8080 0f23996686c8
此时看到
docker跑一个selenium脚本
不用docker的情况
提前下载谷歌游览器和驱动参考:https://www.cnblogs.com/hanfe1/p/13229452.html
[root@VM-0-6-centos /]# pip3 list |grep selenium
[root@VM-0-6-centos auto]# vi baidu.py
from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless') #不需要可视化界面,linux无图形化
chrome_options.add_argument('--no-sandbox') #以最高权限运行
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(executable_path='./chromedriver', options=chrome_options) #找到webdriver浏览器驱动
driver.get("http://www.baidu.com")
print(driver.title)
driver.close()
[root@VM-0-6-centos auto]# python3 baidu.py
百度一下,你就知道
效果如图:
使用容器
练习写的不规范见谅
vi Dockerfile 内容如下
FROM centos:7
ENV LANG=en_US.UTF-8 #中文
ENV TZ=Asia/Shanghai
COPY baidu.py /opt/
RUN mkdir -p /etc/yum.repos.d
RUN yum install wget -y
RUN wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
#down google-chrome
RUN yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm -y
RUN yum install mesa-libOSMesa-devel gnu-free-sans-fonts wqy-zenhei-fonts -y
RUN yum install gcc patch libffi-devel python-devel zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel make -y
RUN mkdir /usr/local/python3
#py3
COPY Python-3.6.5.tgz /usr/local/python3/
RUN set -ex \
&& cd /usr/local/python3 \
&& tar -xzvf Python-3.6.5.tgz \
&& cd Python-3.6.5 \
&& ./configure prefix=/usr/local/python3 \
&& make && make install \
&& cd .. \
&& rm -rf Python-3.6.5 \
&& ln -s /usr/local/python3/bin/python3.6 /usr/local/bin/python3 \
&& ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip3
RUN /usr/local/bin/pip3 install -i https://pypi.douban.com/simple selenium
COPY chromedriver /opt
WORKDIR /opt
RUN pwd
#CMD ["/usr/local/bin/python3","baidu.py"] #容器启动就执行
此时进入容器执行
完成!现在可以把镜像打包下载,发给同事装逼了。。
docker compose
docker-compose用来单机上编排容器(定义和运行多个容器,使容器能互通)
Eg:前端和后端部署在一台机器上,现在直接通过编写docker-compose文件对多个服务(可定义依赖,按顺序启动服务)同时进行启动/停止/更新
注:
docker-compose将所管理的容器分为3层结构:project service container
docker-compose.yml组成一个project,project里包括多个service,每个service定义了容器运行的镜像(或构建镜像),网络端口,文件挂载,参数,依赖等,每个service可包括同一个镜像的多个容器实例。
即为project 包含 service ,service 包含 container
可参考:
docker官网:https://docs.docker.com/compose/gettingstarted/#step-4-build-and-run-your-app-with-compose
常用命令:
docker-compose详解:
#安装
pip3 install -i https://pypi.douban.com/simple docker-compose
#加上下图curl -L 加上自动补全
docker-compose
#测试:
vi docker-compose.yml
和app.py,dockerfile里写的启动容器默认执行app.py