Docker诞生
Docker是dotcloud公司开源的一款产品dotcloud是2010年新成立的一家公司,主要基于PAAS(PlatfromasaService)平台为开发者提供服务。2013年10月dotcloud公司改名为Docker股份有限公司
Docker相关解释
轻量级的虚拟化
,以便隔离进程和资源基于LXC的高级容器引擎
,源代码托管在Github上,基于go语言并遵从Apache2.0协议开源
,PAAS三代Docker与传统虚拟化对比
不同点:
直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟
。因此容器要比传统虚拟机更为轻便。每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
docker仓库
Docker自身组件
封装好的运行环境
Script
[root@localhost ~]$ yum update
[root@localhost ~]$ curl -sSL https://get.docker.com/ | sh
[root@localhost ~]$ systemctl start docker
[root@localhost ~]$ systemctl enable docker
[root@localhost ~]$ docker run hello-world
YUM
```bash
[root@localhost ~]$ yum update
[root@localhost ~]$ cat > /etc/yum.repos.d/docker.repo << EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
[root@localhost ~]$ yum install docker
RPM
docker的官方rpm包下载地址
[root@localhost ~]$ yum -y install iptables-services
[root@localhost ~]$ systemctl start iptables && systemctl enable iptables
[root@localhost ~]$ iptables -F && service iptables save
[root@localhost ~]$ mkdir docker && mv docker* docker/ && cd docker
[root@localhost ~]$ yum -y install *
[root@localhost ~]$ systemctl start docker && systemctl enable docker
[root@localhost ~]$ docker run hello-world
Docker镜像加速配置
阿里云docker官网
[root@localhost ~]$ cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service
[root@localhost ~]$ chmod 777 /etc/systemd/system/docker.service
[root@localhost ~]$ vim /etc/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --registry-mirror=https://kfp63jaj.mirror.aliyuncs.com
[root@localhost ~]$ systemctl daemon-reload
[root@localhost ~]$ systemctl restart docker
[root@localhost ~]$ ps -ef | grep docker
Docker化应用体验
环境准备:
WordPress运行环境需要如下软件的支持:
[root@localhost ~]$ docker pull mariadb #下载镜像
[root@localhost ~]$ docker pull wordpress
[root@localhost docker]$ docker images #查看已经下载好的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mariadb latest e2278f24ac88 12 months ago 410 MB
hello-world latest feb5d9fea6a5 14 months ago 13.3 kB
[root@localhost ~]$ docker run --name db --env MYSQL_ROOT_PASSWORD=example -d mariadb
#docker run 把镜像转换成一个容器
#--name db 给这个镜像起一个名字db
#--env MYSQL_ROOT_PASSWORD=example 指定环境变量
#-d 后台运行容器,并返回容器ID
#mariadb 镜像名字
#docker run是利用镜像生成容器,并启动容器,而docker start是启动一个之前生成过的容器
[root@localhost ~]$ docker run --name MyWordPress --link db:mysql -p 8080:80 -d wordpress
#--link 衔接关系
#-p 端口映射,主机(宿主)端口:容器端口
Docker基础概念
镜像(image)
镜像,简单的来说,就是面向对象中的类,相当于一个模板。Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。封装好的运行环境
容器(container)
Docker 利用容器(Container)独立运行的一个或一组应用。容器是镜像运行完成以后得到的运行环境。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
仓库(repository)
仓库(Repository)是集中存放镜像文件的场所。
Docker指令的基本用法:
docker + 命令关键字(COMMAND) + 一系列的参数
Docker全局基础命令
命令 | 含义 |
---|---|
docker info | 守护进程的系统资源设置 |
docker search | 仓库的查询 |
docker pull | 仓库的下载 |
docker images | Docker镜像的查询 |
docker rmi 镜像id | Docker镜像的删除 |
docker rm | 容器的删除 |
docker ps | 容器的查询 |
docker start/stop | 容器启动停止 |
docker run | 将镜像转换为容器 |
run的扩展
参数 | 含义 |
---|---|
–restart=always | 容器的自动启动(当docker重启后,容器进程依然存在) |
-h x.xx.xx | 设置容器主机名(容器ID) |
–dns xx.xx.xx.xx | 设置容器使用的DNS服务器 |
–dns-search | DNS搜索设置 |
–add-host hostname:IP | 注入hostname<>IP解析到容器内 |
–rm | 服务停止时自动删除(如果不加,则服务停止后,仍保存在ps进程中) |
单一容器管理
每个容器被创建后,都会分配一个CONTAINERID作为容器的唯一标示,后续对容器的启动、停止、修改、删除等所有操作,都是通过CONTAINERID来完成,偏向于数据库概念中的主键
命令 | 含义 |
---|---|
docker ps --no-trunc | 与ps类似,只不过显示containerid id 更完整(16——>128位) |
docker stop/start 容器id | 停止/启动容器 |
docker stop/start 容器名 | 停止/启动容器 |
docker inspect 容器名 | 查看容器所有基本信息 |
docker logs 容器名 | 查看容器日志 |
docker stats 容器名 | 查看容器所占用的系统资源 |
docker exec 容器名 容器内执行的命令 | 容器执行命令(非交互式) |
docker exec -it 容器名 /bin/bash | 进入容器的内部bash |
多容器管理
Docker提倡理念是“一个容器一个进程”,假设一个服务需要多个进程组成,就需要多个容器组成一个系统,相互分工和配合对外提供完整服务。
比如:博客系统
组件1:mariadb
组件2:WordPress 的 apche web
在启动容器时,同一台主机下如果两个容器之间需要有数据交流,使用–link选项建立两个容器之间的互联,上面的docker化应用体验的前提就是mariadb已经提前开启了,否则博客系统无法建立。
docker start db
docker start MywordPress
而如果有上百个上千个微服务时,需要按照顺序去开启,应该怎么做呢?
因此面对这种情况,引入了Docker-Compose!!容器编排工具,允许用户在一个模板(YML格式)中定义一组相关的容器,会根据–link等参数,对启动的优先级进行排序。
Docker-Compose
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
安装Docker-compose
[root@localhost ~]$ curl -Lhttps://github.com/docker/compose/releases/download/1.14.0/docker-compose - `uname-s`-`uname -m` >/usr/local/bin/docker-compose
[root@localhost ~]$ docker version
或者直接上传
[root@localhost docker]$ mv docker-compose /usr/local/bin/
[root@localhost docker]$ chmod a+x /usr/local/bin/docker-compose
[root@localhost docker]$ docker-compose --version
docker-compose version 1.23.1, build b02f1306
Docker-compose用法
参数 | 含义 |
---|---|
-f | 指定使用的yaml文件位置 |
ps | 显示所有容器信息 |
restart | 重新启动容器 |
logs | 查看日志信息 |
config -q | 验证yaml配置文件是否正确 |
stop | 停止容器 |
start | 启动容器 |
up -d | 启动容器项目 |
pause | 暂停容器 |
unpause | 恢复暂停 |
rm | 删除容器 |
yaml文件格式写法示例
[root@localhost ~]$ vim wordpress.yaml
version: '2' #版本
services: #定义一种服务
db: #第一个容器的名字
image: mysql:5.7 #使用的镜像名称
restart: always #在重启docker时,自动启动相关容器。
environment: #环境变量
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress: #第二个容器的名字
depends_on: #相当于--link,做的链接
- db
image: wordpress:latest
restart: always
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
[root@localhost ~]$ mv wordpress.yaml docker-compose.yaml
[root@localhost ~]$ docker-compose up -d #启动
[root@localhost docker]$ docker ps -a #启动成功
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
08fd12c7d0a2 wordpress:latest "docker-entrypoint..." 2 minutes ago Up 2 minutes 0.0.0.0:8000->80/tress_1_d1136d74fc31
b00744035708 mysql:5.7 "docker-entrypoint..." 2 minutes ago Up 2 minutes 3306/tcp, 33060/tcb50ad4392751
f86ed637f976 wordpress "docker-entrypoint..." 2 hours ago Up 2 hours 0.0.0.0:8080->80/t
9bb87d4108e0 mariadb "docker-entrypoint..." 2 hours ago Up 2 hours 3306/tcp
ad30a824ba48 hello-world "/hello" 3 hours ago Exited (0) 3 hours ago onebraker
[root@localhost ~]$ docker-compose logs #查看当前项目的所有日志
[root@localhost docker]$ docker-compose ps #查看docker-compose下服务的状态
Name Command State Ports
-----------------------------------------------------------------------------------------------
docker_db_1_b50ad4392751 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
docker_wordpress_1_d1136d74fc31 docker-entrypoint.sh apach ... Up 0.0.0.0:8000->80/tcp
镜像的特性
①容器创建时需要指定镜像,每个镜像都由唯一的标示ImageID,和容器的ContainerID一样,默认128位,可以使用前16为缩略形式,也可以使用镜像名与版本号两部分组合唯一标示(比如nginx:1.2),如果省略版本号,默认使用最新版本标签latesr
(比如nginx:latesr)
②镜像的分层: Docker的镜像通过联合文件系统(union filesystem)将各层文件系统叠加在一起
bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节省
内存资源
roofs:位于bootfs之上,表现为Docker容器的根文件系统
传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为“只读”模式,完整性自检
完成后将其挂载为读写模式
Docker中,rootfs由内核挂载为“只读”模式,而后通过UFS技术挂载一个“可写”层
③已有的分层只能读,不能修改
④上层镜像优先级大于底层镜像
镜像的生成
①容器转换为镜像
镜像——>容器能够正常运行的前提:工作在前台的守护进程至少一个!!
为什么?因为docker认为,如果现在没有工作在前台的守护进程,那么它起来就没有意义。也就意味着镜像run后,会马上关闭。
示例:现在去docker官网下载一个centos镜像(相当于一个底层的基础镜像,基础镜像里主要集合了一些工具以及类库)
[root@localhost docker]$ docker pull centos:6.8
6.8: Pulling from library/centos
7ce0cebb9dca: Pull complete
Digest: sha256:39abd0c8e375de6fb7334d42ec2a46643f34cbc1bbaf37e2b484065f05eaa7a2
Status: Downloaded newer image for centos:6.8
[root@localhost docker]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mysql 5.7 c20987f18b13 11 months ago 448 MB
mariadb latest e2278f24ac88 12 months ago 410 MB
hello-world latest feb5d9fea6a5 14 months ago 13.3 kB
centos 6.8 82f3b5f3c58f 3 years ago 195 MB
[root@localhost docker]$ docker run --name test centos:6.8 #镜像转换为容器
[root@localhost docker]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29e7cbe5ed64 centos:6.8 "/bin/bash" 17 seconds ago Exited (0) 16 seconds ago test
这里可以发现,test以及exited了。原因就是现在没有前台工作的进程。
所以我们可以去下载一些已经封装好守护进程的镜像。百度网易数帆
[root@localhost docker]$ docker pull hub.c.163.com/public/centos:6.7-tools
...
Digest: sha256:cade8d883b9bde4dc43fd233e4b76e6efd17980b6f61014fab11d666ab7f06ee
Status: Downloaded newer image for hub.c.163.com/public/centos:6.7-tools
这里的hub.c.163.com代表仓库地址
public代表仓库名称
centos:6.7-tools代表镜像名称
[root@localhost docker]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mysql 5.7 c20987f18b13 11 months ago 448 MB
mariadb latest e2278f24ac88 12 months ago 410 MB
hello-world latest feb5d9fea6a5 14 months ago 13.3 kB
centos 6.8 82f3b5f3c58f 3 years ago 195 MB
hub.c.163.com/public/centos 6.7-tools b2ab0ed558bb 5 years ago 602 MB
[root@localhost docker]$ docker run --name mysql -d hub.c.163.com/public/centos:6.7-tools
b49ec81b34fe434fd50a7cce5473027ca12d08009e8c5f1a904f15fd139fa96a
[root@localhost docker]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b49ec81b34fe hub.c.163.com/public/centos:6.7-tools "/usr/bin/supervisord" 30 seconds ago Up 29 seconds 22/tcp mysql
29e7cbe5ed64 centos:6.8 "/bin/bash" 22 minutes ago Exited (0) 22 minutes ago test
这里可以看出,mysql容器已经开始运行了
接下来将进入mysql容器,按照mysql数据库,并进入数据库写入数据
[root@localhost docker]$ docker exec -it mysql /bin/bash
[root@b49ec81b34fe /]$
[root@b49ec81b34fe /]$ yum -y install mysql mysql-server
...
写入数据后
将此容器mysql转换为镜像
[root@localhost docker]$ docker commit mysql mysql:5.1
sha256:ccfceaf31a090661a2db48fb2a4ba31c289a15a7c367bd90c51cae2c79f8b65c
此时再去查看镜像,发现已经又容器转换为镜像了
[root@localhost docker]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.1 ccfceaf31a09 28 seconds ago 604 MB
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mysql 5.7 c20987f18b13 11 months ago 448 MB
mariadb latest e2278f24ac88 12 months ago 410 MB
hello-world latest feb5d9fea6a5 14 months ago 13.3 kB
centos 6.8 82f3b5f3c58f 3 years ago 195 MB
hub.c.163.com/public/centos 6.7-tools b2ab0ed558bb 5 years ago 602 MB
[root@localhost ~]$ docker commit 容器名 镜像名:版本号
例如:
[root@localhost ~]$ docker commit mysql mysql:5.1
[root@localhost docker]$ docker rm -f $(docker ps -a -q) #删除全部容器
08fd12c7d0a2
b00744035708
f86ed637f976
9bb87d4108e0
ad30a824ba48
[root@localhost docker]$ docker ps -a #查看当前所有容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
②Dockerfile
Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image(镜像)
Dockerfile语法
FROM centos:7.2 #有且只有一个
FROM centos
MAINTAINER wangyang"wangyang@itxdl.cn"
RUN cd /tmp && curl-L http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz'|tar-xz
RUN ["/bin/bash","-c","echo hello"]
container启动时指定的操作
。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条CMD echo "Hello World!"
容器启动时执行的命令
,可以多次设置,但是只有最后一个有效ENTRYPOINT ls -l
该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用
Ⅰ当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令
,那么CMD指令和ENTRYPOINT会互相覆盖
只有最后一个CMD或者ENTRYPOINT有效
#CMD指令将不会被执行,只有ENTRYPOINT指令被执行
CMD echo "Hello World!"
ENTRYPOINT ls -l
Ⅱ另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分
;ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
#也就相当于ls -l 组合适用了
USER daemon = ENTRYPOINT ["memcached","-u","daemon"]
#映射一个端口
EXPOSE 22
#相应的运行容器使用的命令
docker run -p port1 image
#映射多个端口
EXPOSE port1 port2 port3
#相应的运行容器使用的命令
docker run -p port1 -p port2 -p port3 image
#还可以指定需要映射到宿主机器上的某个端口号
docker run -p host_port1:port1-p host_port2:port2 -p host_port3:port3 image
ENV JAVA_HOME /path/to/java/dirent
ADD <src> <dest>
<src>是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url;
<dest>是container中的绝对路径
COPY <src> <dest>
FROM base
VOLUME ["/tmp/data"]
WORKDIR /p1 WORKDIR p2 RUN vim a.txt
等同于
RUN cd /p1/p2 && vim a.txt
ONBUILD ADD./app/src
ONBUILD RUN /usr/local/bin/python-build--dir /app/src
创建一个tomcat的dockfile
dockerfile文件
FROM hub.c.163.com/public/centos:6.7 #从hub.c.163.com/public/centos:6.7基础镜像加载
MAINTAINER wangyang@itxdl.cn #打了个标签wangyang@itxdl.cn
ADD ./apache-tomcat-7.0.42.tar.gz /root #添加当前目录下的apache-tomcat-7.0.42.tar.gz到/root下
ADD ./jdk-7u25-linux-x64.tar.gz /root #加当前目录下的jdk-7u25-linux-x64.tar.gz到/root下
ENV JAVA_HOME /root/jdk1.7.0_25 #设置环境变量
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 8080 #暴露8080端口
ENTRYPOINT /root/apache-tomcat-7.0.42/bin/startup.sh && tailf /root/apache-tomcat-7.0.42/logs/catalina.out #启动tomcat并开启前台守护进程(打开一个log文件做前台进程)
如何将dockerfile转换为镜像呢?
[root@localhost ~]$ mkdir /tomcat
[root@localhost ~]$ cd /tomcat
[root@localhost tomcat]$ docker build -t tomcat:v1.0 .
[root@localhost ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat v1.0 af76d6e1ed15 About a
此时已经生成了tomcat的镜像
接下来运行成容器
[root@localhost ~]$ docker run --name tomcat -p 80:8080 -d tomcat:v1.0
2eac813ec870e131e58aa26c60d1e30b665a8ed341947f641ef8d7ec067a3044
[root@localhost ~]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bcaebc2e275 tomcat:v1.0 "/bin/sh -c '/root..." 50 seconds ago Up 49 seconds 22/tcp, 0.0.0.0:80->8080/tcp tomcat
如果docker启动WARNING:IPv4 forwarding is disabled. Networking will not work.
报错解决办法:
vim /etc/sysctl.conf
net.ipv4.ip_forward=1 #开启路由转发功能
sysctl -p #刷新内核
systemctl restart network && systemctl restart docker
环境准备:仓库(10.10.10.150)、客户端(10.10.10.15)
本地上传镜像,必须要求镜像名格式
仓库地址/userName/imageName:tag0(版本号)
[root@localhost ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat v1.0 af76d6e1ed15 About an hour ago 642 MB
mysql 5.1 ccfceaf31a09 44 hours ago 604 MB
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mysql 5.7 c20987f18b13 11 months ago 448 MB
现需要将tomcat这个镜像上传到我们的私有仓库,则需要先改名
[root@localhost ~]$ docker tag tomcat:v1.0 10.10.10.150:5000/tomcat:v1.0
[root@localhost ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.10.10.150:5000/tomcat v1.0 af76d6e1ed15 About an hour ago 642 MB
tomcat v1.0 af76d6e1ed15 About an hour ago 642 MB
mysql 5.1 ccfceaf31a09 44 hours ago 604 MB
wordpress latest c3c92cc3dcb1 11 months ago 616 MB
mysql 5.7 c20987f18b13 11 months ago 448 MB
仓库服务器配置并将改变的镜像上传至私有仓库中:
[root@localhost ~]$ docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always registry
[root@localhost ~]$ vi /etc/docker/daemon.json
{
"insecure-registries":["10.10.10.11:5000"]
}
[root@localhost ~]$ systemctl daemon-reload
[root@localhost ~]$ systemctl restart docker
[root@localhost ~]$ docker push 10.10.10.150:5000/tomcat:v1.0
The push refers to a repository [10.10.10.150:5000/tomcat]
ea961714ca1e: Pushed
fbbc7871451b: Pushed
5f70bf18a086: Pushed
dd70ff5e2c34: Pushed
45abf2f146b4: Pushed
c8032d367084: Pushed
fbb680b07518: Pushed
505749762ec8: Pushed
d8a6a88d2857: Pushed
2e53e90293f6: Pushed
a28cf3a36906: Pushed
v1.0: digest: sha256:c1e84f53d4c4d0e7e9df1059321b65131896161e5b5473fba106b20eda1c7f3c size: 3648
接着客户端测试访问仓库:
[root@localhost ~]$ docker rmi -f $(docker images -q)
[root@localhost ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@localhost ~]$ vi /etc/docker/daemon.json
{
"insecure-registries":["10.10.10.150:5000"]
}
[root@localhost ~]$ systemctl daemon-reload
[root@localhost ~]$ systemctl restart docker
[root@localhost ~]$ curl -XGET http://10.10.10.11:5000/v2/_catalog 查看已有镜像
[root@localhost ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.10.10.150:5000/tomcat v1.0 af76d6e1ed15 About an hour ago 642 MB
[root@localhost ~]$ docker run --name tomcat -p 80:8080 -d 10.10.10.150:5000/tomcat:v1.0
161666f8bb175d6620104f33a710722814cdbb56dd5b7315292463d84a7caf40
[root@localhost ~]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
161666f8bb17 10.10.10.150:5000/tomcat:v1.0 "/bin/sh -c '/root..." 8 seconds ago Up 7 seconds 22/tcp, 0.0.0.0:80->8080/tcp tomcat
此时从私有仓库中下载的镜像,成功运行!!!
但此仓库存在很大安全问题,身份认证没有,任何人只要知道仓库IP即可下载
安装底层需求:
python 2.7或以上
Docker引擎 1.10或以上
Docker Compose 1.6.0或以上
实验构建:
检查版本
[root@localhost ~]# python
Python 2.7.5 (default, Apr 11 2018, 07:36:10)
[root@localhost ~]# docker-compose --version
docker-compose version 1.23.1, build b02f1306
[root@localhost ~]# docker info
...
Server Version: 17.03.0-ce
均满足
安装harbor
[root@localhost ~]# tar -zxf harbor-offline-installer-v1.2.0.tgz
[root@localhost ~]# mv harbor /usr/local/
创建 https 证书以及配置相关目录权限
[root@localhost ~]$ openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...............................+++
...................+++
e is 65537 (0x10001)
Enter pass phrase for server.key: 1234
Verifying - Enter pass phrase for server.key: 1234
[root@localhost ~]$ openssl req -new -key server.key -out server.csr
[root@localhost ~]$ cp server.key server.key.org #备份
[root@localhost ~]$ openssl rsa -in server.key.org -out server.key #输出一个退格的操作,意思就是现在产生的证书在使用nginx的时候需要输入私钥密码,但由于现在的nginx是放在容器里的,启动的时候无法输入密码。所以就会报错退出,因此我们需要设置为启动时不需要输入密钥,所以我们需要退密钥
[root@localhost ~]$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt #创建证书
[root@localhost ~]$ mkdir -p /data/cert
[root@localhost ~]$ chmod -R 777 /data/cert
[root@localhost ~]$ mv server.* /data/cert/
[root@localhost ~]$ cd /data/cert/
[root@localhost cert]$ ls
server.crt server.csr server.key server.key.org
修改/usr/local/harbor/harbor.cfg
[root@localhost cert]$ cd /usr/local/harbor/
[root@localhost harbor]$ ls
common docker-compose.notary.yml harbor_1_1_0_template harbor.v1.2.0.tar.gz LICENSE prepare
docker-compose.clair.yml docker-compose.yml harbor.cfg install.sh NOTICE upgrade
[root@localhost harbor]$ vim harbor.cfg
hostname = www.test.com
harbor_admin_password = 123
ui_url_protocol = https
运行脚本进行安装
/install.sh
[root@localhost harbor]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61065040341c vmware/harbor-jobservice:v1.2.0 "/harbor/harbor_jo..." About a minute ago Up About a minute harbor-jobservice
c57a94fbebdd vmware/nginx-photon:1.11.13 "nginx -g 'daemon ..." About a minute ago Up About a minute 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp nginx
ec793867563a vmware/harbor-ui:v1.2.0 "/harbor/harbor_ui" About a minute ago Up About a minute harbor-ui
5a98575cf0b9 vmware/harbor-adminserver:v1.2.0 "/harbor/harbor_ad..." About a minute ago Up About a minute harbor-adminserver
adc452c98ce3 vmware/registry:2.6.2-photon "/entrypoint.sh se..." About a minute ago Up About a minute 5000/tcp registry
fcb3df1e7ec0 vmware/harbor-db:v1.2.0 "docker-entrypoint..." About a minute ago Up About a minute 3306/tcp harbor-db
efb1117059b9 vmware/harbor-log:v1.2.0 "/bin/sh -c 'crond..." About a minute ago Up About a minute 127.0.0.1:1514->514/tcp harbor-log
测试:首先修改window host文件
账号:admin 密码:123(配置文件中修改的)
接着创建用户
创建项目
[root@localhost harbor]# vim /etc/docker/daemon.json
{
"insecure-registries":["www.test.com"]
}
[root@localhost harbor]# systemctl daemon-reload
[root@localhost harbor]# systemctl restart docker.service
[root@localhost harbor]# vim /etc/hosts
10.10.10.15 www.test.com
[root@localhost harbor]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.10.10.150:5000/tomcat v1.0 af76d6e1ed15 7 hours ago 642 MB
vmware/harbor-log v1.2.0 c7887347f435 5 years ago 200 MB
vmware/harbor-jobservice v1.2.0 1fb18427db11 5 years ago 164 MB
vmware/harbor-ui v1.2.0 b7069ac3bd4b 5 years ago 178 MB
vmware/harbor-adminserver v1.2.0 a18331f0c1ae 5 years ago 142 MB
vmware/harbor-db v1.2.0 deb8033b1c86 5 years ago 329 MB
vmware/registry 2.6.2-photon 5d9100e4350e 5 years ago 173 MB
vmware/postgresql 9.6.4-photon c562762cbd12 5 years ago 225 MB
vmware/clair v2.0.1-photon f04966b4af6c 5 years ago 297 MB
vmware/nginx-photon 1.11.13 285492ff20d6 5 years ago 147 MB
vmware/harbor-notary-db mariadb-10.1.10 64ed814665c6 5 years ago 324 MB
vmware/notary-photon signer-0.5.0 b1eda7d10640 5 years ago 156 MB
vmware/notary-photon server-0.5.0 6e2646682e3c 5 years ago 157 MB
photon 1.0 e6e4e4a2ba1b 6 years ago 127 MB
现在想将tomcat推入仓库中
首先将镜像改名
[root@localhost harbor]# docker tag 10.10.10.150:5000/tomcat:v1.0 www.test.com/siyou/tomcat:v1.0
[root@localhost harbor]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.10.10.150:5000/tomcat v1.0 af76d6e1ed15 7 hours ago 642 MB
www.test.com/siyou/tomcat v1.0 af76d6e1ed15 7 hours ago 642 MB
vmware/harbor-log v1.2.0 c7887347f435 5 years ago 200 MB
vmware/harbor-jobservice v1.2.0 1fb18427db11 5 years ago 164 MB
vmware/harbor-ui v1.2.0 b7069ac3bd4b 5 years ago 178 MB
vmware/harbor-adminserver v1.2.0 a18331f0c1ae 5 years ago 142 MB
vmware/harbor-db v1.2.0 deb8033b1c86 5 years ago 329 MB
vmware/registry 2.6.2-photon 5d9100e4350e 5 years ago 173 MB
vmware/postgresql 9.6.4-photon c562762cbd12 5 years ago 225 MB
vmware/clair v2.0.1-photon f04966b4af6c 5 years ago 297 MB
vmware/nginx-photon 1.11.13 285492ff20d6 5 years ago 147 MB
vmware/harbor-notary-db mariadb-10.1.10 64ed814665c6 5 years ago 324 MB
vmware/notary-photon signer-0.5.0 b1eda7d10640 5 years ago 156 MB
vmware/notary-photon server-0.5.0 6e2646682e3c 5 years ago 157 MB
photon 1.0 e6e4e4a2ba1b 6 years ago 127 MB
[root@localhost harbor]# docker push www.test.com/siyou/tomcat
The push refers to a repository [www.test.com/siyou/tomcat]
ea961714ca1e: Preparing
fbbc7871451b: Preparing
5f70bf18a086: Retrying in 5 seconds
dd70ff5e2c34: Preparing
45abf2f146b4: Preparing
c8032d367084: Waiting
fbb680b07518: Waiting
505749762ec8: Waiting
d8a6a88d2857: Waiting
2e53e90293f6: Waiting
a28cf3a36906: Waiting
denied: requested access to the resource is denied
由于没有登录,所以是拒绝。
现在需要登录
[root@localhost harbor]# docker login www.test.com
Username: admin
Password:
Login Succeeded
再次去push,则成功了!!!
[root@localhost harbor]# docker push www.test.com/siyou/tomcat
The push refers to a repository [www.test.com/siyou/tomcat]
ea961714ca1e: Pushed
fbbc7871451b: Pushed
5f70bf18a086: Pushed
dd70ff5e2c34: Pushed
45abf2f146b4: Pushed
c8032d367084: Pushed
fbb680b07518: Pushed
505749762ec8: Pushed
d8a6a88d2857: Pushed
2e53e90293f6: Pushed
a28cf3a36906: Pushed
v1.0: digest: sha256:c1e84f53d4c4d0e7e9df1059321b65131896161e5b5473fba106b20eda1c7f3c size: 3648
namespace 系统调用参数 隔离内容 内核版本
UTS CLONE_NEWUTS 主机名和域名 2.6.19
IPC CLONE_NEWIPC 信号量、消息队列和共享内存 2.6.19
PID CLONE_NEWPID 进程编号 2.6.24
NetWork CLONE_NEWNET 网络设备、网络栈、端口等 2.6.29
Mount CLONE_NEWNS 挂载点(文件系统) 2.4.19
User CLONE_NEWUSER 用户和用户组 3.8
Docker中的防火墙规则
容器访问外部网络(防火墙nat转换)
[root@localhost ~]$ iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE
外部网络访问容器(dnat转换)
[root@localhost ~]$ docker run -d -p 80:80 apache
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL-j DOCKER
iptables -t nat -A DOCKER !-i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
– dns用于指定启动的容器的DNS
–net用于指定容器的网络通讯方式,有以下四个值
- bridge:Docker默认方式,网桥模式
- none:容器没有网络栈
- container:使用其它容器的网络栈,Docker容器会加入其它容器的network namespace
- host:表示容器使用Host的网络,没有自己独立的网络栈。容器可以完全访问Host的网络,不安全
- p/P选项的使用格式
-p : <ContainerPort>:将制定的容器端口映射至主机所有地址的一个动态端口
-p <HostPort>:<ContainerPort>:映射至指定的主机端口
-p <IP>::<ContainerPort>:映射至指定的主机的IP的动态端口
-p <IP>:<HostPort>:<ContainerPort>:映射至指定的主机IP的主机端口
-P(大):暴露所需要的所有端口
[root@localhost ~]$ docker port ContainerName #可以查看容器当前的映射关系
{
"bip": "192.168.1.5/24",
"fixed cidr" : "10.20.0.0/16",
"fixed cidr-v6": "2001:db8::/64",
"mtu": "1500"",
"default-gateway": "10.20.1.1",
"default-gateway vf6": "2001:db8:abcd;:89",
"dns":["10.20.1.2","10.20.1.3"]
}
[root@localhost ~]$ docker network ls #查看当前可用的网络类型
[root@localhost ~]$ docker network create -d 类型 网络空间名称 #类型网络空间名称
#类型分为:
overlay 覆盖型网络,主要是不同的主机/容器之间能够互相通信
bridge
使用不同的网络名字空间进行隔离
[root@localhost ~]$ docker network create -d bridge lamp
[root@localhost ~]$ docker network create -d bridge lnmp
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
df9c23e1959d bridge bridge local
66f11b5b4ce2 docker_default bridge local
156502f879f2 harbor_harbor bridge local
5cc4d71d9762 host host local
ea3ebb154509 lamp bridge local
17aa1c538978 lnmp bridge local
7c7d53537228 none null local
[root@localhost ~]$ docker run --name tomcat11 --network=lamp -d tomacat:v1.0
[root@localhost ~]$ docker run --name tomcat111 --network=lnmp -d tomcat:v1.0
[root@localhost ~]# docker exec -it /bin/bash
"docker exec" requires at least 2 argument(s).
See 'docker exec --help'.
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
[root@localhost ~]# docker exec -it tomcat11 /bin/bash
[root@b57194c430a2 /]#
[root@b57194c430a2 /]# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:14:00:02
inet addr:172.20.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe14:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:32 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3298 (3.2 KiB) TX bytes:648 (648.0 b)
[root@localhost ~]# docker exec -it tomcat111 /bin/bash
[root@3a21dae08568 /]# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:15:00:02
inet addr:172.21.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe15:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:24 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2650 (2.5 KiB) TX bytes:648 (648.0 b)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[root@3a21dae08568 /]# ping 172.20.0.2
PING 172.20.0.2 (172.20.0.2) 56(84) bytes of data.
此时发现两个项目的ip相互隔离了!!!
使容器配置上独立IP进行通讯
①配置真实网桥
[root@localhost ~]$ cd /etc/sysconfig/network-scripts
[root@localhost network-scripts]$ vi ifcfg-ens33
DEVICE=ens33
HWADDR=00:0C:29:06:A2:35
TYPE=Ethernet
UUID=34b706cc-aa46-4be3-91fc-d1f48c301f23
ONBOOT=yes
BRIDGE=br0 #添加这里
NM_CONTROLLED=yes
BOOTPROTO=static
[root@localhost network-scripts]$ vi ifcfg-br0
#改成这样
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.10.10.15
NETMASK=255.255.255.0
DNS=8.8.8.8
默认情况下docker不能借助这个dr0通信,因此需要使用工具
②使用工具分配地址
[root@localhost ~]$ yum install -y git
[root@localhost ~]$ git clone https://github.com/jpetazzo/pipework
#将代码克隆到操作系统
[root@localhost ~]$ cp pipework/pipework /usr/local/bin/
[root@localhost ~]$ chmod a+x /usr/local/bin/pipework
[root@localhost ~]$ docker run --name tomcat --net=none -d tomcat:v1.0
[root@localhost ~]$ pipework br0 tomcat 10.10.10.15/24
数据卷特性
解决方案:数据卷
卷是容器上一个或多个目录,此类目录可绕过ufs,与宿主机上的某目录“绑定”
[root@localhost ~]$ docker run -it --name roc -v MOUNTDIR roc/lamp:v1.0
或者直接dockerfile里添加 VOLUME,比如
[root@localhost ~]$ vim Dockerfile
FROM centos:6.8
RUN touch /tmp/1.txt
RUN mkdir /data
VOLUME /data
CMD tail -f /tmp/1.txt
[root@localhost ~]$ cd /var/lib/docker/volumes #存储数据卷
Bind-mount Volume
[root@localhost ~]$ docker run --name roc -v 宿主机目录:容器目录 -d roc/lamp:v1.0
扩展:绑定卷可以实现不同容器之间的共享目录
Union Volume(联合卷,需要与docker自管理卷联合使用)
[root@localhost ~]$ docker run -it --name roc --volumes-from ContainerName roc/lamp:v1.0
存储驱动
Docker存储驱动(storage driver)是Docker的核心组件,它是Docker实现分成镜像的基础
[root@localhost ~]$ mkdir upper work merged low #创建挂载目录
[root@localhost ~]$ mount -t overlay overlay-olowerdir=./low,upperdir=./upper,workdir=./work./merged
修改为overlayfs存储驱动
[root@localhost ~]$ echo "overlay" > /etc/modules-load.d/overlay.conf
[root@localhost ~]$ cat /proc/modules|grep overlay
[root@localhost ~]$ reboot
[root@localhost ~]$ vim /etc/systemd/system/docker.service
storage-driver=overlay\
重点提示
1、为应用做内存压力测试,理解正常业务需求下使用的内存情况,然后才能进入生产环境使用
2、一定要限制容器的内存使用上限
3、尽量保证主机的资源充足,一旦通过监控发现资源不足,就进行扩容或者对容器进行迁移
4、如果可以(内存资源充足的情况),尽量不要使用swap,swap的使用会导致内存计算复杂,对调度器非常不友好
内存限制设置方式
在docker启动参数中,和内存限制有关的包括(参数的值一般是内存大小,也就是一个正数,后面跟着内存单位b、k、m、g,分别对应bytes、KB、MB、和GB):
-m --memory:容器能使用的最大内存大小,最小值为4m
--memory-swap:容器能够使用的swap大小
--memory-swappiness:默认情况下,主机可以把容器使用的匿名页(anonymouspage)swap出来,你可以设置一个0-100之间的值,代表允许swap出来的比例
--memory-reservation:设置一个内存使用的softlimit,设置值小于–m设置
--kernel-memory:容器能够使用的kernelmemory大小,最小值为4m。
--oom-kill-disable:是否运行OOM的时候杀死容器。只有设置了-m,才可以把这个选项设置为false,否则容器会耗尽主机内存,而且导致主机应用被杀死
Docker提供的CPU资源限制选项可以在多核系统上限制容器能利用哪些vCPU。而对容器最多能使用的CPU时间有两种限制方式:
[root@localhost ~]$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04 /bin/bash
[root@localhost ~]$ docker run -it --cpu-period=10000 --cpu-quota=20000 ubuntu:16.04 /bin/bash
--cpuset-cpus="" 允许使用的CPU集,值可以为0-3,0,1
-c,--cpu-shares=0 CPU共享权值(相对权重),默认值1024
--cpuset-mems="" 允许在上执行的内存节点(MEMs)
--cpu-period=0 即可设置调度周期,CFS周期的有效范围是1ms~1s,对应的--cpu-period的数值范围是1000~1000000
--cpu-quota=0 设置在每个周期内容器能使用的CPU时间,容器的CPU配额必须不小于1ms,即--cpu-quota的值必须>=1000,单位微秒
--cpus 能够限制容器可以使用的主机CPU个数,并且还可以指定如1.5之类的小数
限制性实验
[root@localhost ~]$ docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress-vm2
[root@localhost ~]$ docker run --name stress -it --rm --cpus 2 lorel/docker-stress-ng:latest stress --cpu 8
[root@localhost ~]$ docker run --name stress -it --rm --cpuset-cpus 0 lorel/docker-stress-ng:latest stress --cpu 8
修改/etc/docker/daemon.jason
"hosts":["tcp://0.0.0.0:2375","unix://var/run/docker.sock"]
Client:
docker -H ip:port Command