Docker入门笔记
- 什么是Docker
2013年被开源后发展的非常快,现在在云计算中是一个非常火热的话题。运维、开发、微服务的概念。
Docker 确实不是虚拟机
运行并映射nginx服务,替换nginx服务的页面。
但是这样改变的页面,在Docker容器内部的改变都只是暂时的。是没有被保存下来的,如果想保存可以使用commit命令来保存
Docker运行的常用命令
如何在大的服务器中配置多个服务器,每个服务器能配置什么环境,资源利用最大化
Centos 7 下安装 docker
1.安装:命令如下
# yum –y install docker
# yum -y install docker-ce
如果提示:
则输入一下命令即可:
# rm –rf /var/run/yum.pid
2.验证docker 是否安装完成
# docker info
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
3.启动docker
#systemctl start docker
4.测试运行hello-world
# docker run hello-world
5.Docker 卸载:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
rm -rf /etc/systemd/system/docker.service.d
rm -rf /var/lib/docker
rm -rf /var/run/docker
二、Docker的用处
高效便捷的虚拟化
云计算的新宠儿
超级集装箱
三、虚拟化与Docker
Docker 是一种容器级虚拟化技术
四、容器与虚拟机
五、Docker 组件
1.Docker 镜像,只读不可写。(为了更好的保证数据的安全)
2.Docker的容器,容器之间是互不干扰的隔离的。
3.Docker 的仓库,用来下载和上传镜像的。
六、什么是镜像
七、如何获取镜像
- 开启docker
# systemctl start docker
- 获取镜像
# docker pull ubuntu:15.02
他是从http://registry.hub.docker.com/中的ubuntu下载的
在上面搜索ubuntu 查找相应的版本号,并下载。一个镜像有多层,会一层一层的下载。
过程中可能需要停止doceker 然后在启动.再安装
# systemctl stop docker
# systemctl start docker
八、如何搜寻镜像
- 搜寻镜像
# docker search hello (搜寻名称中有hello的镜像)
- 可以自动化构建的对象
# docker search --automated hello
- 收藏数
# docker search –s 3 hello
- 等级为2以上的
# docker search --stars=2 hello
- 不截取描述
# docker search --no-trunc hello
九、Docker-part 如何创建镜像
创建镜像:
- 查看镜像
# docker images
根据已有的镜像进行修改
- 运行一个容器 基于ubuntu运行一个容器
# docker run -ti ubuntu:14.04 /bin/bash
容器的ID:d2ef31c788a4
- 镜像的容器中中创建目录
# mkdir test
- 创建文件
# touch abc.text
退出之后说明容器已经被修改,我们需要重新封装成一个镜像
- 把修改好的镜像重新变成一个镜像
# docker commit -m 描述 –a 用户 容器号 新的名称:TAG
# docker commit -m "this is a new images" -a "jeffrey" d2ef31c788a4 ubuntuu:1889
这样我们就根据原有的镜像创建了一个新的镜像
根据本地模板导入镜像
- 从官方提供的模板下载自己需要的模板,并复制其连接。
https://wiki.openvz.org/Download/template/precreated
- 通过命令下载,如果没有安装wget,可以通过# yum -y install wget 安装
# wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
- 基于下载的模版去创建一个新的镜像命令
# cat debian-7.0-x86-minimal.tar.gz | docker import - ubuntu:7789
使用Dockerile创建镜像
Dockerfile 语法:
- 创建文件夹,并在新的文件夹里面创建文件Dockerfile,
# mkdir test
# touch Dockerfile
- 编辑该文件
# vi Dockerfile
FROM ubuntu:7789 #从哪里创建
MAINTAINER jeffrey #自己的用户信息
RUN touch a.txt #进行哪些操作
RUN mkdir jeffrey
- 创建一个新的镜像
# docker build -t=”ubuntutu” /test/
4.执行docker images 查看镜像
- 如何删除镜像
- 如何删除镜像呢
# docker rmi ubuntututu
此命令只会删除名称为“ubuntututu” 并且TAG为latest的镜像,默认补全为latest
# docker rmi 273fc938d6f2
此命令根据ID去删除
- 如果删除报错
说明该镜像正在被使用
- 那么首先要找出运行的镜像,并通过ID删除
(使用镜像运行一个容器:# docker run -ti ubuntutu:7789 /bin/bash)
# docker ps -a
# docker rm ff8d151a654c (放入容器ID的前4位即可:# docker rm ff8d)
- 镜像信息的查看
- 查看命令
# docker images
REPOSITORY:仓库名
TAG:标签、可以理解为镜像的版本号
IMAGE ID:镜像的ID号,唯一
CREATED:创建时间
SIZE:镜像大小
- 镜像的存出与载入
- 镜像存出
# docker save -o ubuntutu-bak.tar ubuntutu:xyv1.0
将ubuntutu:xyv1.0备份为ubuntutu-bak.tar
- 镜像的载入
首先删除某个镜像
载入:
# docker load --input ubuntutu-bak.tar
- 写时复制机制
如图可以看出子进程省略了一部分物理空间,也就是共用了一部分物理空间(所有东西的运行都需要在物理空间上),也就提高了机器的运行速度。
Docker的写时复制机制
总结:什么是写时复制机制?在父进程创建子进程的时候,只要父进程内容不发生改变,那么子进程和父进程就可以共用一段物理空间,以此来节约了大量的内存空间。
- 什么是Docker Hub
Docker Hub的网址是:https://hub.docker.com
Docker Mirror 的官网地址:https://www.daocloud.io/
注册后可添加主机,根据提示进行安装即可。
当我们下载镜像会首先从Docker Mirror中下载,如果没有在到Docker Hub中下载。
- 镜像分发
-
-
-
- 把镜像对应的压缩文件发布出去
-
-
- 使用github的方式
Github上主要是存放镜像的压缩文件
打包相应的镜像
# docker save –o hello-world.tar docker.io/hello-world
上传hello-world到github
# yum install -y git
# ssh-****** -t rsa -C "CentOs"
[[email protected] .ssh]# cd ~/.ssh/
[[email protected] .ssh]# ls
id_rsa id_rsa.pub known_hosts
[[email protected] .ssh]# vi id_rsa.pub
获取id_rsa.pub里面的密匙配置到github中
打开Settings,添加SSH keys,这样就配置完成。
然后添加一个名为pei-docker的仓库,完成后测试。
# git clone [email protected]:peyxy/pei-docker.git
完成配置。
# git remote add origin [email protected]:githubname/dockerfile
# git add hello-world.tar
# git commit –m “this is hello-world images to tar”
# git push origin master #分发出去
关于把镜像上传到仓库,详见第十八节
- 自动化构建镜像
1.首先两个平台都要有账号
下载github中的仓库
# git clone [email protected]:peyxy/pei-docker.git
在linux中创建Dockerfile
# touch Dockerfile
# vi Dockerfile
FROM ubuntu
RUN touch a.txt
完成后上传到pei-docker 中的根目录
# cd .git
# vi config
# git commit -m "This is My automated images"
# git push origin master
上传成功。在github中可以查看
可以查看到镜像的指令
注意:我们的Dockerfile 文件只能上传到仓库的根目录下
然后在DockerHub中根据github中的文件自动换创建。
Dockerhub改版后自动化构建有些变化,需要首先建立github的链接
创建过程省略
- 注册服务器的创建
之前我们已经创建了dockerhub的账号,以及自动化的构建。下面我们创建仓库以及登录。
首先在Docker Hub中创建一个名为hello的仓库
使用指令登录Dockerhub
# docker login
并输入用户名密码
- 镜像的上传
标记本地镜像,将其归入某一仓库
账号名/仓库名: TAG 如:ijeffrey/hello:first
# docker tag fce2 ijeffrey/hello:first # fce2为ID的前4位
上传
# docker push ijeffrey/hello:first
镜像上传成功
- 容器创建实战
创建容器:
使用docker创建容器,需要分配一个伪终端(-t),还要绑定到容器的标准输出中,保持标准输出打开状态(-i),容器基于镜像,指定镜像名(ubuntu:7789)
,对应容器运行的地址
# docker run -t -i ubuntu:7789 /bin/bash
这里的容器的操作就是在伪终端中操作的。
- 容器管理实战
查看容器
# docker ps –a
启动容器(根据ID输入ID的前四位也可)
# docker start 5fd3735d285d
也可理解为后台运行
选定14.04 镜像为基准创建一个容器,以守护太的方式来创建(-d)
设置一个循环每个一段时间有个输出
# docker run -d ubuntu:14.04 /bin/bash -c "while true ;do echo Thanks;sleep 2 ;done"
查看容器的运行
# docker logs ba53973e2340
终止容器
# docker stop ba539
- 依附容器
只有容器在运行状态下才能依附
# docker attach ba53973e2340
启动
# docker start ba53973e2340
- 容器信息的查看
查看运行的容器
# docker ps
查看所有的容器
# docker ps –a
查看最后创建的容器
# docker ps –l
只列出正在运行容器的ID
# docker ps –q
静态查看
# docker logs ba53973e2340
事实动态显示
# docker logs -f ba53973e2340
默认输出两行,然后每隔两秒自动输出
# docker logs -f --tail=2 ba53973e2340
输出最近的7行
# docker logs --tail=7 ba53
显示输出的具体的时刻
# docker logs -t ba53
多个参数拼接
# docker logs --tail=2 -t -f ba53
- 容器内命令执行实战
1.依附到容器
只有容器在运行状态下才能依附
# docker attach 5fd3
2.不进入相应的容器
2.1后台执行
# docker exec -d 5fd3 touch /8989.txt
2.2交互执行
# docker exec -ti 5fd3 mkdir /hello20190509
那么这两种方式有什么区别呢?具体见下图:
后台执行不能返回交互信息。没看到“>>>”,并不代表其没执行,它已经在后台执行,只是没交互信息,前台看不到。另外的交互执行把交互信息返回了前台,我们可以在前台进行操作。
- 容器的导入导出
容器ba53973e2340 导出 名称为ba539.tar
# docker export ba53973e2340 > ba539.tar
把文件导入为一个镜像:
# cat ba539.tar | docker import - bac:v2
根据镜像bac:v2创建一个容器
# docker run -ti bac:v2 /bin/bash
只是ID号不一样,容器里面的东西都是一样的
这样就完成了容器的导入
- 什么是数据卷
数据卷就是一个特殊的目录,主要用来解决容器与容器之间以及容器与主机之间的数据共享问题
数据卷的特性
数据卷的创建(-v)
基于镜像创建容器
# docker run -ti -v /abctest ubuntu:7789 /bin/bash
abctest就是一个数据卷
- 挂载
从母机器的gztext(目录)挂载到容器中的contest(数据卷)
# docker run -ti -v /gztest:/contest bac:v2 /bin/bash
在数据中更改在母机中也可以看到更改后的文件。
如果过程中遇到权限的问题可以通过--privileged=true 来解决
文件挂载
创建文件abc.txt 后挂载
# docker run -ti -v /abc.txt:/co/b.txt --privileged=true bac:v2 /bin/bash
- 数据卷容器
如果我们要解决数据的持久化问题,我们应当选用数据卷容器
创建镜像名称为datac1的数据卷容器,并在根目录下创建abc
# docker run -ti -v /abc --name datac1 ubuntu:14.04
如果遇到:docker: Error response from daemon: No command specified.
说明是镜像有问题,换个镜像即可
其中abc就是一个数据卷,可以通过abc给别人传递数据,实现数据共享
持久化存储Volume:
提供独立于容器之外的持久化存储,也可以提供容器和同期之间的共享数据
测试数卷容器
创建普通容器,在该容器中挂载(--volumes-from efe4)到数据卷容器datac1中的abc目录。
# docker run -ti --volumes-from efe4c17e8b03 --name test666 ubuntu:14.04
紧接着发现里面存在数据卷,在里面新建个文件,并退出。进入到数据卷容器
1.启动数据卷容器:
# docker start efe4
2.进入到数据卷容器:
# docker attach efe4
- 数据迁移.备份
备份数据卷和恢复备份数据卷,实现数据卷转移
备份:
1.加载数据卷容器里面的数据卷
2.新创建容器
3.新容器中就会有加载的数据卷
4.然后在新容器中归档(可以简单理解为压缩)数据卷(tar xvf aa.tar aa)
5.存储到新容器里面新的目录下
6.将当前目录挂载到新容器存放归档文件的目录
7.这样在当前目录就可以操作压缩文件
-
-
-
-
-
-
- 创建数据卷容器
-
-
-
-
-
# docker run -ti -v /hh --name sjj ubuntu:14.04
2.存在数据卷hh,创建几个文件、文件夹
3.以交互式的方式创建新的容器并加载开始的数据卷容器(当前目录挂载到容器内部目录,backup:压缩文件存在的目录)
# docker run -ti --volumes-from sjj -v $(pwd):/backup --name tast123 ubuntu:14.04 tar cvf /backup/task1.tar /hh
注:如果出现错误 Connot open:permission denied 代表权限的问题
解决办法:关闭selinux,查看是否开启# getenforce,输入:# setenforce 0 关闭,输入:# setenforce 1 开启
4.备份完成
恢复:
1.进入压缩文件的目录
2.创建新容器
把当前目录挂载到新容器的某个目录:这样压缩文件就很方便的传到了容器了面。
# docker run -ti -v $(pwd):/hf --name hf123 ubuntu:14.04
这样hf就和我们主机的当前目录绑定了
3.解档
# tar xvf task1.tar
4.完成数据卷的迁移
- 通过网络访问容器
-
-
-
- 外部访问
-
-
方式一:
创建容器,配置网络信息(-P),端口(--expose),使用-t 表面出错
# docker run -t -P --expose 95 --name net1 ubuntu:14.04
绑定了新容器中的95端口
如果该容器中存在web服务通过网址访问即可:http://cloud.vessel.com:32769/
方式二:
配置网络信息(-p) 本机的IP地址:IP地址对应的端口号:容器的端口号:5000
# docker run -t -p 127.0.0.1:26:5000 --name net3 ubuntu:14.04
如果该容器中存在web服务通过网址访问即可:http://cloud.vessel.com:26/
-
-
-
- 容器互联
-
-
容器互联通过—link参数进行
1.首先创建一个容器hl1(源容器)
# docker run -t --name hl1 ubuntu:14.04
2.创建一个容器hl2(接收容器)并连接容器hl1(别名:yuan1)
# docker run -ti --name hl2 --link hl1:yuan1 ubuntu:14.04
3.这样两个容器就可以实现了连接
- 网络配置的查看
一、ps
新建容器
# docker run -t -p 127.0.0.1:27:5007 --name w1 ubuntu:14.04
查询
# docker ps
二、port:# docker port 容器 端口
# docker port w1 5007
- 容器命名
通过容器的ID来找容器的名字Name中第一个字母大写
# docker inspect -f "{{.Name}}" dfd5ce9d3906
Docker不允许存在相同的名字
重名的解决方案:
1.先删除原容器,再创建新容器
# docker rm w1
如果正在运行,先停止
# docker stop w1
2.使用—rm标记
创建时增加 --rm 如果容器正常运行,就正常运行不受影响。一旦容器停止,系统就会自动删除掉
# docker run -ti --name h789 --rm ubuntu:14.04
- 容器连接
1.hosts文件发
上面我们建立了两个容器 hl1 和 hl2
进入连接容器
# docker start hl2
# docker attach hl2
[email protected]:/# cat /etc/hosts
Ping 名称也可以:可以看到
2.环境变量法
通过环境变量查看(env)
# docker run --rm --name hl3 --link hl1:yuanh1 ubuntu:14.04 env
这样就是hl3和hl1的链接信息,展示信息中源容器的别名大写
- Dockerfile的使用
CMD指令只能有一条,如果有多条只会执行最后一条,CMD具有替换性
ENTRYPOINT 不具有替换性
USER 使用哪个用户运行容器
EXPORT 指定哪个端口
ENV 环境变量
CMD:
在Dc1中创建Dockerfile
# vi Dockerfile
FROM ubuntu:14.04
MAINTAINER jeffrey
CMD ["echo"]
docker build 命令用于使用 Dockerfile 创建镜像
# docker build -t="dnew:v1" /Dc1
使用dnew:v1 创建一个容器
# docker run dnew:v1 echo hello
寻找跟CMD命令有没有重合的 发现echo 是一样的,因为echo 有替换性,所以相同的指令被替换,只输出hello
ENTRYPOINT:
创建新镜像
# vi Dockerfile
FROM ubuntu:14.04
MAINTAINER jeffrey
ENTRYPOINT ["echo"]
# docker build -t="dnew:v2" /Dc2
使用dnew:v2 创建容器:
# docker run dnew:v2 echo hello
因为ENTRYPOINT 不具有替换性,所以会输出echo hello
- 实战项目一:快速创建SSH服务镜像
1.工具的安装
创建容器,并安装shh服务,创建完容器根据新的容器去创建一个镜像,这样我们新的镜像就会有ssh服务
# docker run -ti --name dssh1 ubuntu:14.04
[email protected]:/# apt-get update
安装openssh-server
[email protected]:/# apt-get install openssh-server
完成。
如果要运行shh那么有个目录要用到就是 /var/run/sshd
创建sshd
[email protected]:/# mkdir /var/run/sshd
启动ssh服务
[email protected]:/# /usr/sbin/sshd -D &
这样就启动了一个端口号为3038的ssh服务
ssh的服务默认绑定22端口
查看运行的程序
[email protected]:/# ps aux
我们可以把容器当做服务器,linux本身当做客户端
首先在客户端生成秘钥
# ssh-****** -t rsa
在服务器端root下创建一个.ssh
在.ssh中创建一个名为:authorized_keys 的文件
[email protected]:~/.ssh# vi authorized_keys
把服务端的私钥 内容粘贴到authorized_keys中
这样就绑定好了。
把容器封装成为一个镜像
# docker commit 772d723fac3a sshd:v1
封装成功之后,以后基于这个sshd:v1镜像创建任何容器都会支持ssh服务。
这样就封装好了一个支持shh服务的镜像。
然后基于新的镜像创建一个新的容器(需要配置端口以及映射信息)
# docker run -p 127.0.0.1:8089:22 -ti sshd:v1
在新容器中启动ssh服务
[email protected]:/# /usr/sbin/sshd -D &
通过客户端访问该容器(客户端必须安装ssh)
方式一:
# ssh 用户名&IP地址 -p 端口
说明连接成功。
方式二:
获取容器/镜像的元数据: docker inspect
# docker inspect ed40be6cb2f7
找到IP通过IP连接:
# ssh [email protected]
- 实战项目二:Docker下构建LAMP环境
LAMP镜像获取
# docker pull tutum/lamp
环境搭建
基于镜像创建容器(最好使用守护态来创建-d),需要两个端口apache和MySQL都需要,外部端口8981映射到容器内的80端口
# docker run -d -p 8981:80 -p 5306:3306 tutum/lamp
这样就创建完成,可以通过命令测试
# curl 127.0.0.1:8981
通过网页测试:
输入:http://cloud.vessel.com:8981/
可以搭建我们自己的网站
可以通过Dockerfile来完成(Dockerfile是基于某个镜像创建一个新镜像)
在创建新镜像的时候,我们把原来镜像里面的环境的网页的信息,替换成我们自己的,那么这个新容器就是我们自己新网站的信息
首先把我们的程序上传到github上,然后在基于Dockerfile来创建出来
首先新建一个文件夹
# mkdir lam
# vi Dockerfile
FROM tutum/lamp:latest #基于lamp创建一个新镜像
#删除项目,把我们自己的项目放到里面
RUN rm -rf /app &&git clone https://github.com/peyxy/wsjdzf.git /app
#绑定端口号
EXPOSE 80 3306
#运行
CMD ["/run.sh"]
创建镜像
# docker build -t="xinjingxiang:v1" /lam
LAMP中MySQL的基本链接信息
查看某个容器运行的信息
# docker logs ap63
Mysql的默认用户是root 默认没有密码
链接即可
docker-compose
多容器 app
docker-compose 独立运行与docker
先下载一个二进制文件,下载地址:
# curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose
“>”:表示把下载的文件重定向到/usr/local/bin/ 中
uname –s 和 uname –m 返回结果如下
操作把文件变成可执行的:
# chmod a+x /usr/local/bin/docker-compose
检查版本是否可用
# docker-compose --version
docker-compose.yml文件配置项
docker-compose.yml 文件不仅指定正在使用的容器,还指定如何单独配置各容器。常用的配置项如下所示:
- build:定义镜像生成,可以指定Dockerfile文件所在的目录路径,支持绝对路径和相对路径;
- image:从指定的镜像中启动容器,可以是存储仓库、标签以及镜像 ID,如果镜像不存在,Compose 会自动拉去镜像;
- environment:定义环境变量和配置;
- ports:定义端口映射,比如上面配置中将容器上的公开端口 80 转接到主机上的外部端口 9901和9902;
- depends_on,定义依赖关系。此定义会让当前服务处于等待状态,直到这些依赖服务启动。比如某个服务依赖数据库服务,那么通过此配置解决了服务的启动顺序的问题;
- volumes,挂载一个目录或者一个已存在的数据卷容器,可以直接使用 HOST:CONTAINER 这样的格式,或者使用 HOST:CONTAINER:ro 这样的格式,后者对于容器来说,数据卷是只读的,这样可以有效保护宿主机的文件系统;
- context,指定Dockerfile 的文件路径,也可以是到链接到 git 仓库的 url;
- args,指定构建参数,这些参数只能在构建过程中访问;
- target,定义构建指定的阶段Dockerfile,比如针对不同阶段使用不同的dockerfile,开发阶段使用支持编译调试的dockerfile,而生产环境,则使用轻量级的dockerfile;command,覆盖默认命令;
- container_name,指定自定义容器名称,而不是生成的默认名称。
由于篇幅有限,我们就不提供过多介绍和示例了。不过我们建议大家访问此地址,来做一个全面的了解:
https://docs.docker.com/compose/compose-file/#reference-and-guidelines
最后,分享几个小技巧:
- 可以通过配置项depends_on来定义依赖关系,这点对于控制服务的执行顺序尤为重要,比如先启动数据库然后再启动web服务。
- 如何使用JSON文件进行配置?可以指定文件名称,如下所示:
docker-compose -f docker-compose.json up
- 如何分阶段构建?推荐使用target配置项。