layout: p
title: Docker使用
date: 2019-07-25 10:58:19
tags:
- 自动化运维
Docker学习
轻部署,省成本,易迁移
docker和虚拟机VM的区别
一、本质上的区别:
VM(VMware)在宿主机器、宿主机器操作系统的基础上创建虚拟层、虚拟化的操作系统、虚拟化的仓库,然后再安装应用;
Container(Docker容器),在宿主机器、宿主机器操作系统上创建Docker引擎,在引擎的基础上再安装应用。
那么问题来了,没有操作系统,怎么运行程序?
可以在Docker中创建一个ubuntu的镜像文件,这样就能将ubuntu系统集成到Docker中,运行的应用就都是ubuntu的应用。
二、使用上的区别:
Size:
- 虚拟机ubuntu大小为:24.1GB
- Docker中镜像文件占用内存: 81.2MB
Startup:
- Docker在宿主机器的操作系统上创建Docker引擎,直接在宿主主机的操作系统上调用硬件资源,而不是虚拟化操作系统和硬件资源,所以操作速度快。
- 这个其实安装一个ubuntu的虚拟机和拉取一个Docker的ubuntu镜像文件,运行一下就知道了,区别很明显,虚拟机开一下大概得2分多钟,而Docker只需要2秒钟。
宿主机、镜像与容器
宿主机器: 运行docker的机器
镜像:不可以修改内容
容器:可以修改能内容,相当于虚拟机,默认情况下彼此相互独立(容器之间可以通信)
△.可以依据镜像来创建容器,也可以封装容器为一个镜像,即容器<===>镜像
Docker命令
搜索镜像: docker search python
下载镜像: docker pull NAME
创新容器: docker run -tid (--name xxx) IMAGE ID
- ti表示以交互的形式创建容器,d表示不进入
- -d, --detach=false, 指定容器运行于前台还是后台,默认为false
- -i, --interactive=false, 打开STDIN,用于控制台交互
- -t, --tty=false, 分配tty设备,该可以支持终端登录,默认为false
运行容器: docker start CONTAINER_ID
进入容器: docker attach CONTAINER_ID
- 进入容器前得前运行容器
退出容器: ctrl + p + q , 以ctrl + z 、exit将会终止容器运行
封装容器为镜像: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停。
容器通信-创建子节点链接中心节点: docker run -tid (--name xxx) (--link CONTAINER_NAMES) IMAGE ID
查看容器ip: cat /ect/hosts
root@b68943564e76:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 test 4e02c004539e
172.17.0.3 b68943564e76
▲初次使用, ifconfig使用无效,ping也无效,原因如下
我创建的容器是拉取的Base镜像,而因为用Docker拉取的Base镜像如Centos和Ubuntu的话都是最简版本,不包含Ping工具,而对Docker进行Docker network和Docker链接操作时往往要用到Ping工具测试两个容器间的网络,此时就要用到Ping工具了,下面是Ubuntu下安装Ping工具的命令:apt-get update && apt-get install iputils-ping、安装ifconfig工具:apt install net-tools
从容器里面拷文件到宿主机
docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径
宿主机上执行:$ docker cp testtomcat:/usr/local/tomcat/webapps/test/js/test.js /opt
从宿主机拷文件到docker容器里面
docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径
宿主机上执行$ docker cp requirements.txt apptest:/app
▲注:容器NAME可以通过docker ps命令查看
Dockerfile指令
Dockerfile文件D一定要大写
$ docker build -t="dormanctpress/df_test2" .
- .为Dockerfile的路径
1.FROM :
2.MAINTAINER
3.RUN
- 镜像构建中运行的命令
4.EXPOSE
- 如果是端口的话,只是声明会使用xx端口,但是实际使用时还是需要run -p xx $ docker build -t="dormanctpress/df_test2" .
- 设置环境变量
CMD
- 在容器运行时运行的默认命令(命令行中添加的命令可以代替掉Dokcerfile中写的CMD指令)
- 每个Dockerfile只能够包含一个CMD,多个CMD 只有最后一个能有效
- 定义的三种方式
- CMD这个会当做/bin/sh-c“cmd”来执行
- CMD[“executable","arg1","arg2"]
- 一定要双引号
- CMD[“arg1","arg2"],这个时候CMD作为ENTRYPOINT的参数
ENTRYPOINT
- 每个Dockerfile只能够包含一个ENTRYPOINI,多个ENTRYPOINT只有最后一个能有效
- 不会像CMD命令一样被覆盖,除非使用``
- 当定义了ENTRYPOINT后,CMD将被作为参数使用。如果定义了CMD,那么docker run -t test/osf2 xxxx后面即xxxx的内容全会被当做参数传递ENTRYPOINT
组合使用ENTRYPOINT和CMD: ENTRYPOINT指定命令,CMD指定默认参数
ADD©
共同点
- ADD©的源必须在context路径下
- 当在源代码构建的方式下,可以通过ADD和COPY的方式,把Host上的文件或者目录复制到Image
ADD - 包含类似tar解压的功能
- 当src为网络URL的情况下,ADD指令可以把它下载到Dest的指定位置,这个在任何build的方式下都可以Work
COPY
- 如果单纯复制文件,Docker推荐COPY
- ADD©的源必须在context路径下
- 当在源代码构建的方式下,可以通过ADD和COPY的方式,把Host上的文件或者目录复制到Image
VOLUME['/data']
- 设置数据卷
WORKDIR /path/to/workdir
- 一般使用绝对路径
ENV
- 用来设置环境变量,后续的RUN可以使用它所创建的环境变量。
- 当创建基于该镜像的Container的时候,会自动拥有设置的环境变量
USER daemon
- 指定UID或者username,来决定运行RUN指令的用户
- 如果不指定,则默认root
ONBUILD
- 触发器
dockerfile构建过程
- 从基础镜像运行一个容器
- 执行一条指令,对容器做出修改
- 执行类似docker commit的操作,提交一个新的镜像层
- 再基于刚提交的镜像运行一个新容器
- 执行Dockerfile中的下一条指令,直至所有指令执行完毕
使用中间层镜像进行调试
查找错误
Dockerfile 镜像缓存
构建缓存:将之前的镜像缓存
不使用缓存docker build --no-cache
查看镜像构建的过程
查看构建过程:docker history xxx/yyy
数据卷
sudo docker run -v ~/container_data:/data -it ubuntu/bin/bash
参数说明:使用-v选项,第一个参数为宿主机目录,:后的目录为在容器中使用的目录(挂载)
查看容器是否挂载了数据卷
docker inspect CONTAINER_ID可以查看容器是否挂载了数据卷
给数据卷增加权限
sudo docker run -v ~/datavolume:/data:ro -it ubuntu/bin/bash
ro是read-only
数据卷容器
命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器
挂载数据卷容器的方法
docker run--volumes-from [CONTAINER NAME]
MySQL通信
>>> can't connect to MySQL server on '172.17.0.8'(111)
$ vim /etc/mvsal/my.cnf
# 将bind-address=127.0.0.1注释掉
>>> Host '2eaf92ef2ff6'is not allowed to connect to this MySQL server
$ create user "weiwei"@"%"identified by"weijc7789"
# 创建用户
$ grant create, select, update, delete, insert on *.* to weiwei;
# 增添权限
$ mysq1-h 172.17.0.8-u weiwei-p
# 链接
redis通信
$ redis-cli -h 172.17.0.8
>>> Could not connect to Redis at 172.17.0.8:6379:Connection refused
$ vim /etc/redis /redis.conf
# 将bind-address=127.0.0.1注释掉
# 如果修改后/ect/init.d/redis-server restart后还是链接不了,重启进入容器
$ redis-cli-h 172.17.0.8-p 6379
一条命令实现停用并删除容器:
docker stop $(docker ps -q) & docker rm $(docker ps -aq)
一条命令删除所有镜像:
docker rmi `docker images -q`
一条命令删除创建失败的镜像:
docker images | sed -n '2p' | awk '{print$3}' | xargs docker rmi
附录
Dockerfile RUN,CMD,ENTRYPOINT命令区别
RUN命令执行命令并创建新的镜像层,通常用于安装软件包
CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换
ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)
Shell格式和Exec格式运行命令
我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式:
- Shell格式:。例如:apt-get install python3
- 多条命令用&&链接
- Exec格式: ["executable", "param1", "param2", ...]。例如: ["apt-get", "install", "python3"]
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。
总结
- 使用 RUN 指令安装应用和软件包,构建镜像。
- 如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
- 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。
Docker 运行python flask的web程序
1创建镜像
1.1 ubuntu16.04+python3.6
18.04卡在了PPA环节,并且git安装也没安装上,后来使用了dockerHub上搜素到的github仓库中的16.04 Xenial就解决了。
注:镜像TAG版本需要到dockerHub上才能查看,最初下载成18.04就是因为这个原因被坑了
18.04PPA问题:
aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for Ubuntu/bionic意思是18.04该PPA没有资源.bionic是版本代号,如16.04的 Xenial
⑴使用下载好的Xenial的Dockerfile进行创建镜像docker run 1604ubuntu .
为了使用国内源用阿里云,先编辑一个sources.list,放在dokcerfile同目录下,作为docker创建镜像时的上下文。
deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
⑵根据官方的镜像来编写自己的Dockerfile创建具有工具的Ubuntu1604
涉及交互式选择项(如下),docker build的时候会报错。设置 DEBIAN_FRONTEND=noninteractive
FROM 1604ubuntu
MAINTAINER mrli
#用ubuntu国内源替换默认源
RUN rm /etc/apt/sources.list
COPY sources.list /etc/apt/sources.list
#安装python3.6必要的包。源镜像太精简了,ip ifconfig之类的都没有。后续安装python pip也需要一些。但是build_essential似乎不必须,先去了。如果后面安装numpy之类需要gcc了,再加上
RUN apt update
#RUN apt upgrade
RUN apt install -y apt-utils apt-transport-https vim iproute2 net-tools ca-certificates curl build-essential wget python-software-properties software-properties-common psmisc
#安装python3.6 来自第三方
RUN add-apt-repository ppa:jonathonf/python-3.6
RUN apt update
RUN apt install -y python3.6
RUN apt install -y python3.6-dev
RUN apt install -y python3.6-venv
#为3.6安装pip
RUN wget https://bootstrap.pypa.io/get-pip.py
RUN python3.6 get-pip.py
#设置默认python为python3
RUN update-alternatives --install /usr/bin/python python /usr/bin/python2 100
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 150
#和自带的3.5共存,设置python3默认为3.6
#RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2
# 更新配置
RUN update-alternatives --config python3
#print()时在控制台正常显示中文
ENV PYTHONIOENCODING=utf-8
在dockerfile所在路径下执行,建立image
docker build -t uos:1604 .
因为开头几步用了国内源,所以非常快。
1.2 开发环境
再建一个dockerfile,开头使用刚才建立的镜像uos1604
FROM uos:1604
MAINTAINER mrli
#代码复制过来后的路径
RUN mkdir /app
# 指定容器启动时执行的命令都在app目录下执行
WORKDIR /app
# 将本地app目录下的内容拷贝到容器的app目录下
COPY ./app/ /app/
# 安装nginx
RUN apt -y install nginx mysql-server
RUN /etc/init.d/nginx start
# 替换nginx的配置
RUN rm /etc/nginx/sites-enabled/default
RUN cp nginx.conf /etc/nginx/sites-enabled/nginx.conf
RUN pip3 install uwsgi
#安装需要的python库
# 启动nginx和uwsgi
#ENTRYPOINT pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package --no-cache-dir && service nginx restart && uwsgi --ini uwsgi.ini
# 为了保证能之后进入所以最后一个命令为/bin/sh
ENTRYPOINT pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package --no-cache-dir && service nginx restart && uwsgi --ini uwsgi.ini & && /bin/sh
创建uflask镜像:docker build -t uflask .
根据镜像创建运行容器:docker run -tid -p 12345:80 flaskdemo IMAGE_ID
此时就可以通过VPS的IP地址:宿主机端口访问这个应用程序
查看日志:docker logs 应用名(NAMES)如docker logs flaskdemo
关于mysql的建议
mysql建议作为单独容器来跑数据库,然后远程连接数据库.或是使用数据卷
#
# 搜索
# docker search mysql
# 拉取
# docker pull mysql:5.7
#运行
# docker run --name mysql5.7 -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 -d mysql:5.7
2启动容器(转)
Docker
一种开源容器应用,供开发者打包自己的开发环境,可以任意移植docker-compose
一种管理多个Docker容器的工具,可以简化我们启动容器的各种命令
2.1手动敲docker命令
先试试用docker命令行启动容器:
docker run --name quotation_api -itd -p 5000:5000 -v /home/quotation:/code quotation_dev:latest
用到的参数分别是
--name为容器命名;
-itd 输入输出终端,后台运行
-p host端口:容器端口
- 将宿主机5000端口的请求转发到容器5000端口,用5000是flask默认
-v host路径:容器内路径(挂载数据卷)
quotation_dev:latest 最后是使用的镜像名(前面刚用dockerfile build出来的)
然后进入容器
docker attach quotation_api
用python3 main.py启动flask,OK。
这样flask运行在docker里了。
在host改代码,可以看见docker的控制台在更新,和在host一样了。(使用数据卷)
2.2使用dock-compose
如果没有安装先进行安装apt install docker-compose
dock-compose用来管理多个container的运行,特别适合1个host上跑多个container的情况。
得天独厚,docker官网上dock-compose的gettingstarted文档就是flask的(说明flask+docker代表了先进生产力的前进方向O Yeah!),看完了基本就能用了。
dock-compose采用yaml作为配置文件。查了一下,yaml参考了xml和json,以及python的语法,采用了python之缩进,无XML之标记,无json之括号,无字符串之引号。特别适合作为配置文件用。
建立docker-compose.yaml文件(无镜像,但有dockerfile):
version: '2' # 表示该 Docker-Compose 文件使用的是 Version 2 file
services:
docker-demo: # 指定服务名称
build: . # 指定 Dockerfile 所在路径
ports: # 指定端口映射
- "9000:8761"
建立docker-compose.yaml文件(已有镜像):
version: "3"
services:
quotation_api: # 指定服务名称
image: quotation_dev:latest # 指定镜像
volumes: # 选择数据卷
- /home/quotation:/code
ports: # 端口映射
- "5000:5000"
command: python3 main.py # 执行命令
基本对应手动敲的docker命令,最后还省了敲python3 main.py。
当然如果是部署,这句可以用CMD 写进Dockfile。但是开发过程,文件名之类的会改变,比如最终部署运行用可能是gunicorn+wsgi.py,所以还是写在dockerfile外面比较方便
运行,在控制台执行:docker-compose up、docker-compose up -d // 后台启动并运行容器
docker-compose更多介绍
坑点记录
docker容器启动后马上退出解决方案
dokcerfile中的最后一个命令不能在后台执行,不然会启动后马上退出
原因
Docker容器同时只能管理一个进程,如果这个进程退出那么容器也就退出了,但这不表示容器只能运行一个进程(其他进程可在后台运行),但是要使容器不退出必须有一个前台执行的进程。
解决方法:
脚本中最后一个进程一定要用前台运行方式即在进程最后不加&(&表示后台运行),否则容器会退出。
如何正确的使用docker attach
Q:由于执行着uwsgi --ini uwsig.ini命令,用户就无法直接进入到容器中去,docker attach CONTAINER_id 就会一直卡着。
A: attach早已过时了,可用: docker exec -it containerID /bin/bash,一开始使用的是/bin/sh然后还是一直卡住.但是/bin/bash是可以的
附Uuntu版本代号:
版本号 代号 发布时间
18.04 Bionic Beaver(仿生海狸) 即将发布2018年4月(LTS)
17.10 Artful Aardvark(机灵的土豚) 2017年10月
16.04 LTS Xenial Xerus 好客的非洲地松鼠 即将发布 2016/4
15.10 Wily Werewolf 狡诈的狼人 2015/10/22
15.04 Vivid Vervet 活泼的小猴 2015/04/23
14.10 Utopic Unicorn 乌托邦独角兽 2014/10/23
14.04 LTS Trusty Tahr 值得信赖的塔尔羊 2014/04/18
13.10 Saucy Salamander 活泼的蝾螈 2013/10/17
13.04 Raring Ringtail 铆劲浣熊 2013/04/25
12.10 Quantal Quetzal 缤纷的绿咬鹃 2012/10/18
12.04 LTS Precise Pangolin 精准的穿山甲 2012/04/26
11.10 Oneiric Ocelot 有梦的虎猫 2011/10/13
11.04 Unity成为默认桌面环境 Natty Narwhal 敏捷的独角鲸 2011/04/28
10.10 Maverick Meerkat 标新立异的的狐獴 2010/10/10
10.04 LTS Lucid Lynx 清醒的猞猁 2010/04/29
9.10 Karmic Koala 幸运的无尾熊 2009/10/29
9.04 Jaunty Jackalope 活泼的兔子 2009/04/23
8.10 Intrepid Ibex 无畏的高地山羊 2008/10/30
8.06 官方查不到此版本发布信息 Haughty Husky 骄傲的哈士奇 2008/06/07
8.04 LTS Hardy Heron 坚强的苍鹭 2008/04/24
7.10 Gutsy Gibbon 勇敢的长臂猿 2007/10/18
7.04 Feisty Fawn 烦躁不安的小鹿 2007/04/19
6.10 Edgy Eft 尖利的小蜥蜴 2006/10/26
6.06 LTS Dapper Drake 整洁的公鸭 2006/06/01
5.10 Breezy Badger 活泼的獾 2005/10/13
5.04 Hoary Hedgehog 白发得刺猬 2005/04/08
4.10 初始发布版本 Warty Warthog 多疣的疣猪 2004/10/20
docker-compose使用[转]
docker-compose常见命令
ps:列出所有运行容器
docker-compose ps
logs:查看服务日志输出
docker-compose logs
port:打印绑定的公共端口,下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口
docker-compose port eureka 8761
build:构建或者重新构建服务
docker-compose build
start:启动指定服务已存在的容器
docker-compose start eureka
stop:停止已运行的服务的容器
docker-compose stop eureka
rm:删除指定服务的容器
docker-compose rm eureka
up:构建、启动容器
docker-compose up
kill:通过发送 SIGKILL 信号来停止指定服务的容器
docker-compose kill eureka
- pull:下载服务镜像
scale:设置指定服务运气容器的个数,以 service=num 形式指定
docker-compose scale user=3 movie=3
run:在一个服务上执行一个命令
docker-compose run web bash
docker-compose.yml 字段含义
- version:指定 docker-compose.yml 文件的写法格式
- services:多个容器集合
build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 参数
build: ./dir
---------------
build:
context: ./dir
dockerfile: Dockerfile
args:
buildno: 1command:覆盖容器启动后默认执行的命令
command: bundle exec thin -p 3000
----------------------------------
command: [bundle,exec,thin,-p,3000]dns:配置 dns 服务器,可以是一个值或列表
dns: 8.8.8.8
------------
dns:
- 8.8.8.8
- 9.9.9.9dns_search:配置 DNS 搜索域,可以是一个值或列表
dns_search: example.com
------------------------
dns_search:
- dc1.example.com
- dc2.example.comenvironment:环境变量配置,可以用数组或字典两种方式
environment:
RACK_ENV: development
SHOW: 'ture'
-------------------------
environment:
- RACK_ENV=development
- SHOW=tureenv_file:从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量
env_file: .env
---------------
env_file:
- ./common.envexpose:暴露端口,只将端口暴露给连接的服务,而不暴露给主机
expose:
- "3000"
- "8000"image:指定服务所使用的镜像
image: java
network_mode:设置网络模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"ports:对外暴露的端口定义,和 expose 对应
ports: # 暴露端口信息 - "宿主机端口:容器暴露端口"- "8763:8763"
- "8763:8763"
links:将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
links: # 指定服务名称:别名
- docker-compose-eureka-server:compose-eurekavolumes:卷挂载路径
volumes:- /lib
- /var
logs:日志输出信息
--no-color 单色输出,不显示其他颜.
-f, --follow 跟踪日志输出,就是可以实时查看日志
-t, --timestamps 显示时间戳
--tail 从日志的结尾显示,--tail=200
更新容器
- 当服务的配置发生更改时,可使用 docker-compose up 命令更新配置
- 此时,Compose 会删除旧容器并创建新容器,新容器会以不同的 IP 地址加入网络,名称保持不变,任何指向旧容起的连接都会被关闭,重新找到新容器并连接上去
links
服务之间可以使用服务名称相互访问,links 允许定义一个别名,从而使用该别名访问其它服务
version: '2'
services:
web:
build: .
links:
- "db:database"
db:
image: postgres这样 Web 服务就可以使用 db 或 database 作为 hostname 访问 db 服务了