docker学习笔记

原创
2015/09/17 12:21
阅读数 3K

1,安装

CentOS6

# rpm -ivh http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm

#rpm -ivh http://mirrors.ustc.edu.cn/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

#yum install docker-io

源码安装

http://blog.rage.net/2013/08/04/installing-docker-on-centos-6/


CentOS7

#yum install docker



安装之后启动 Docker 服务,并让它随系统启动自动加载。



2,启动docker

#service docker start

#chkconfig docker on


3,获取镜像

获取官方镜像

+# docker pull centos:latest  官方镜像

+# docker pull docker.cn/docker/centos:centos6  国内镜像


搜索镜像

[root@localhost ~]# docker search centos


定制docker镜像

+openVZ模板的下载地址为:http://wiki.openvz.org/Download/template/precreated

+#cat centos-5-x86.tar.gz  | docker import - centos:5



本地制作docker镜像

+安装镜像制作工具febootstrap

+#yum -y install febootstrap

+使用febootstrap 制作CentOS5镜像目录

+febootstrap -i bash -i wget -i yum -i iputils -i iproute -i man -i vim-minimal -i openssh-server -i openssh-clients -i cronie-anacron -i crontabs centos5 centos5-image http://mirrors.aliyun.com/centos/5/os/x86_64/

+将镜像导入到Docker

+cd centos5-image && tar -c . | docker import - centos5-base


++执行rpm -qa报错:http://www.opstool.com/article/318


从dockerfile创建

后面会详细介绍


节点之间的导入导出docker镜像

+首先需要运行docker镜像,如果不运行镜像,执行docker ps -a,就没有正在运行的container。

+[root@localhost ~]# docker run -i -t treasureboat/centos6 /bin/bash

+[root@ef6ad6a64086 /]# ifconfig 

+[root@localhost ~]# docker ps -a

CONTAINER ID        IMAGE                         COMMAND             CREATED             STATUS                     PORTS               NAMES

ef6ad6a64086        treasureboat/centos6:latest   "/bin/bash"         23 seconds ago      Exited (0) 8 seconds ago                       mad_mclean   

+[root@localhost ~]# docker commit ef6ad6a64086 centos6.6.image

4e6e72b4387d8fe6c1c94a0546b105ab738cecee32a7332e93e13edf816cbcf2

+有两种方法导出

++[root@localhost ~]# docker export centos6.6.image > centos6.6.img

++[root@localhost ~]# docker save centos6.6.image > centos6.6.image


+导入docker镜像

++[root@localhost ~]# docker load < /root/centos6.6.img




4,搭建私有仓库

+方法一

++直接pull registry镜像

[root@localhost ~]# docker pull registry

++默认情况下,会将仓库存放于容器内的/tmp/registry目录下,这样如果容器被删除,则存放于容器中的镜像也会丢失,所以我们一般情况下会指定本地一个目录挂载到容器内的/tmp/registry下,如下:

[root@localhost ~]#docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry

35bdd9ed60d8653102ee17cf956099bd6114b68061fcdc172657ea3140a16be6

[root@localhost ~]# docker ps -a

CONTAINER ID        IMAGE                         COMMAND             CREATED             STATUS                           PORTS                    NAMES

7ec1030ff3bf        registry:latest               "docker-registry"   3 seconds ago       Up 1 seconds                     0.0.0.0:5000->5000/tcp   desperate_elion      


可以看到启动了一个容器,地址为,本地ip地址:5000




+方法二

++使用git上的源码创建

++首先登陆到docker在git上面的源码页面,https://registry.hub.docker.com/_/registry/下载,解压。

++安装registry到本地服务器上

++yum install build-essential python-dev libevent-dev python-pip liblzma-dev

++pip install docker-registry

++运行registry

++gunicorn --access-logfile - --debug -k gevent -b 0.0.0.0:5000 -w 1 docker_registry.wsgi:application


+方法三

++基于方法二的源码,build成image,然后执行image

++在docker——registry目录里

++docker build -t registry

++docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry




上面的方法都需要指定-v来修改镜像默认的存放位置,还可以修改配置文件:


[root@localhost ~]#git clone https://github.com/dotcloud/docker-registry

[root@localhost ~]#cd docker-registry


[root@localhost ~]#cp config_sample.yml config.yml

[root@localhost ~]#vi config.yml

...

# This is the default configuration when no flavor is specified

dev:

    storage: local

    storage_path: /home/vpsee/registry

    loglevel: debug

...


[root@localhost ~]#mkdir /home/vpsee/registry


Docker-Registry 实际上是个基于 Flask 的 web app,安装成功后就cb可以这样运行了:

[root@localhost ~]#gunicorn --access-logfile - --debug -k gevent -b 0.0.0.0:80 -w 1 wsgi:application


打开浏览器,访问 IP 地址就可以看到 docker-registry 私有仓库在运行了


使用私有仓库

+查看一下现有系统上已经有了哪些镜像:

[root@localhost ~]# docker  images

REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

centos6.6.image        latest              4e6e72b4387d        About an hour ago   465.7 MB

<none>                 <none>              cf73ddbcb12b        10 days ago         375 MB

treasureboat/centos6   latest              09365809850b        4 months ago        465.7 MB


+将centos6.6.image这个镜像上传(pull)到创建的私有仓库中(ip地址就是本地的ip地址),初次pull会提示设置用户名/密码。

[root@localhost ~]# docker images

REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

centos6.6.image        latest              4e6e72b4387d        About an hour ago   465.7 MB

registry               latest              70d8f0edf5c9        7 days ago          413.9 MB

treasureboat/centos6   latest              09365809850b        4 months ago        465.7 MB

+只有images中的镜像可以pull。

[root@localhost ~]# docker tag 4e6e72b4387d  10.1.5.96:5000/c6.6


经测试,在centos6.6 docker1.5 无法push镜像

[root@localhost ~]# docker push 10.1.5.96:5000/c6.6

FATA[0004] Error: v1 ping attempt failed with error: Get https://10.1.5.96:5000/v1/_ping: EOF. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry 10.1.5.96:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/10.1.5.96:5000/ca.crt 


说明:docker1.3.× 以后,docker registry交互默认使用https,然而搭建的私有仓库只提供http服务,所以当与私有仓库交互是就会报上面的错误,为了解决这个问题需要在启动docker server时增加启动参数为默认使用http访问。

解决方法:

修改docker配置文件

vi /etc/sysconfig/docker

DOCKER_OPTS="--insecure-registry 10.1.5.96:5000"

重启docker

service docker restart

--------------------------------------------------------------------------------

docker数据管理


1,挂载本地目录

#docker run -it --privileged=true -v /data/test:/usr/local/test treasureboat/centos6 /bin/bash

-v参数,冒号前为宿主机目录,必须为觉得路径,冒号后为镜像内挂载的路径。

默认挂载的路径权限为读写,如果指定只读可以用:ro

#docker run -it --privileged=true -v /data/test:/usr/local/test:ro treasureboat/centos6 /bin/bash


遇到的问题:

使用docker run -v /data:/mnt -i -t ubuntu 来共享docker容器和主机目录,但是在docker容器里文件只可以读不可以写。如果共享的不是主机data目录,文件也会变得不可以读,用ls命令会得出ls: cannot open directory .: Permission denied这样的提示,根本查看不了目录。

解决:

selinux 原因。

两种方法:1.selinux模式为permissive模式 setenforce 0

         2.容器启动,添加--privileged=true


数据卷

数据卷:就是一个正常的容器,专门用来提供数据卷供其他容器挂载

实例:

#docker run --privileged=true  -v /data/test:/usr/local/test --name mydata  docker.io/treasureboat/centos6 /bin/bash

创建一个数据卷

#docker run -it --privileged=true  --volumes-from mydata  docker.io/treasureboat/centos6 /bin/bash

创建一个容器,挂载数据卷容器,并做操作

[root@localhost ~]# docker ps -a

CONTAINER ID    IMAGE                                   COMMAND       CREATED              STATUS                          PORTS               NAMES

c10abf449ad4    docker.io/treasureboat/centos6:latest   "/bin/bash"   About a minute ago   Exited (0) About a minute ago                 thirsty_mclean      

ce8dc9e26363    docker.io/treasureboat/centos6:latest   "/bin/bash"   18 minutes ago       Exited (0) 18 minutesago                           mydata    


[root@localhost ~]# docker run -it --privileged=true  --volumes-from mydata  docker.io/treasureboat/centos6 /bin/bash

[root@c10abf449ad4 /]# echo "aaa" > /usr/local/test/aaa.txt

[root@c10abf449ad4 /]# exit

exit

[root@localhost ~]# cat /data/test/aaa.txt 

aaa


备份

新建一个数据卷

docker run --privileged=true  -v /root/data:/data --name mydata docker.io/plaken/centos6.5:latest data

挂载数据卷,并将数据卷中的/data打包保存到本地目录/root/test下

[root@localhost ~]# docker run --privileged=true   --volumes-from mydata -v /root/test:/backup docker.io/plaken/centos6.5:latest tar zcvf /backup/backup.tar.gz /data

tar: Removing leading `/' from member names

/data/

/data/bbb.txt

[root@localhost ~]# cd test/

[root@localhost test]# ls

backup.tar.gz


恢复

删除原有的文件

[root@localhost ~]# cd data/

[root@localhost data]# ls

bbb.txt

[root@localhost data]# rm -rf bbb.txt 

挂载数据卷,并将本地的备份文件/root/test/backup.tar.gz 解压到数据卷中的/data中,也就是本地的/root/data/data/bbb.txt

[root@localhost ~]# docker run --privileged=true --volumes-from mydata -v /root/test:/backup docker.io/plaken/centos6.5:latest tar zxvf /backup/backup.tar.gz -C /data

data/

data/bbb.txt

[root@localhost ~]# ll data/data/bbb.txt 

-rw-r--r--. 1 root root 4 7月   9 03:12 data/data/bbb.txt



2,docker配置sshd

1>,进入交互模式

[root@localhost ~]# docker run -i -t docker.io/treasureboat/centos6  /bin/bash

2>,安装sshd服务

[root@c1915e9fa3fc /]# yum  install  openssh-server

3>,修改密码

[root@c1915e9fa3fc /]# passwd root

4>,关闭selinux

[root@c1915e9fa3fc /]#setenforce 0

[root@c1915e9fa3fc /]#echo "setenforce 0" >> /etc/rc.d/rc.local

5>,修改配置文件

 vi /etc/ssh/sshd_config

UsePAM yes 修改为 UsePAM no



7>,commit改容器

[root@localhost ~]# docker ps -a

CONTAINER ID        IMAGE                                   COMMAND             CREATED             STATUS                     PORTS               NAMES

c1915e9fa3fc        docker.io/treasureboat/centos6:latest   "/bin/bash"         15 minutes ago      Exited (0) 4 seconds ago                       high_davinci        

[root@localhost ~]# docker commit c1915e9fa3fc centos6:sshd


8>,使用docker.io/treasureboat/centos6:latest /usr/sbin/sshd -D

[root@localhost ~]# docker run -d -p 60022:22 docker.io/treasureboat/centos6:latest /usr/sbin/sshd -D


3,使用网络

外部访问容器

要让外部访问容器的端口可以通过-p或-P参数来指定端口映射

当使用-P参数时,会随机一个49000~49900的端口到内部容器开放的网络端口

格式:

1>hostPort:contarnerPort

docker run -d -p 60022:22 docker.io/treasureboat/centos6:latest /usr/sbin/sshd -D

2>ip:hostPort:contarnerPort

docker run -d -p 127.0.0.1:60022:22 docker.io/treasureboat/centos6:latest /usr/sbin/sshd -D

3>ip::contarnerPort

docker run -d -p 127.0.0.1::22 docker.io/treasureboat/centos6:latest /usr/sbin/sshd -D

4>指定udp端口

docker run -d -p 127.0.0.1:600161:161/udp docker.io/treasureboat/centos6:latest /bin/snmp -D

查看映射端口配置

docker port mydocker 5000

127.0.0.1:5000


容器互联

A服务器(172.17.0.100)

[root@localhost ~]# docker run -i -t --name client  docker.io/nepalez/ubuntu-ssh:latest /usr/sbin/sshd -D

B服务器(172.17.0.101)

[root@localhost ~]# docker run -i -t --link=client:lianjie  docker.io/nepalez/ubuntu-ssh:latest /bin/bash

root@84a8b509cd82:/# ping lianjie

PING lianjie (172.17.0.100) 56(84) bytes of data.

64 bytes from lianjie (172.17.0.100): icmp_seq=1 ttl=64 time=0.049 ms

64 bytes from lianjie (172.17.0.100): icmp_seq=2 ttl=64 time=0.040 ms

64 bytes from lianjie (172.17.0.100): icmp_seq=3 ttl=64 time=0.047 ms



容器间db链接

打开mysql容器

[root@localhost ~]# docker run -a stdout --name mydb  -P  docker.io/umrigark/centos6-ssh-mysql /run.sh &

========================================================================

 ssh -p <port> root@<host>

 Password for the root user is : mz0pbPqWgWgD 

 Please remember to change the above password as soon as possible!

========================================================================

....

========================================================================

 MySQL Password for user: admin  is : ePpd2cBEXwTn 

 Please remember to change the above password as soon as possible!

========================================================================

打开应用容器

[root@localhost ~]# docker run -t -i --link mydb:db docker.io/umrigark/centos6-ssh-mysql /bin/bash

安装mysql客户端,连接mysql服务器

bash-4.1# mysql -h db -P3306 -uadmin -p

Enter password: 

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 12

Server version: 5.1.73 Source distribution


Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.


Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.


Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| test               |

+--------------------+

3 rows in set (0.00 sec)


mysql> 


4,高级网络设置

配置dns

1>默认情况下容器的dns配置是利用虚拟文件来挂载到容器的三个文件。所以当宿主机的DNS配置改变,容器也跟着改变。

bash-4.1# mount

...

/dev/sda3 on /etc/resolv.conf type xfs (rw,seclabel,relatime,attr2,inode64,noquota)

/dev/sda3 on /etc/hostname type xfs (rw,seclabel,relatime,attr2,inode64,noquota)

/dev/sda3 on /etc/hosts type xfs (rw,seclabel,relatime,attr2,inode64,noquota)

...

2>手动指定容器配置

在创建容器的时候添加以下参数

-h HOSTNAME 或者 --hostname=HOSTNAME 设定容器的主机名。它会被写到容器内的/etc/hostname和/etc/hosts,但在容器外部看不到,既不会在docker ps中显示,也不会在其他的容器/etc/hosts看到

--dns=IP_ADDRESS 添加DNS服务器到容器的/etc/resolv.conf



3>访问控制

利用iptables对容器的访问进行控制

iptables使用问题

[root@localhost ~]# docker run -i -t  docker.io/plaken/centos6.5 /bin/bash

bash-4.1# iptables -nL

FATAL: Could not load /lib/modules/3.10.0-229.7.2.el7.x86_64/modules.dep: No such file or directory

iptables v1.4.7: can't initialize iptables table `filter': Permission denied (you must be root)

Perhaps iptables or your kernel needs to be upgraded.

解决方法:

[root@localhost ~]# docker run -i -t --privileged=true docker.io/plaken/centos6.5 /bin/bash

bash-4.1# iptables -nL

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         


Chain FORWARD (policy ACCEPT)

target     prot opt source               destination         


Chain OUTPUT (policy ACCEPT)

target     prot opt source               destination  




4>自定义docker网桥

创建容器的时候,默认会创建一个docker0的网桥,该网桥和其他虚拟机的网桥的功能是一样的,可以使用brctl show来查看。

*brctl的安装包是bridge-utils

[root@localhost ~]# brctl show

bridge name bridge id STP enabled interfaces

docker0 8000.56847afe9799 no veth40bd9a4

vethee0474f

除了默认的docker0网桥,用户也可以指定网桥来连接各个容器

在启动docker服务的时候使用-b BRIDGE或 --bridge=BRIDGE来指定使用的网桥

自定义网桥:

停止docker服务

[root@localhost ~]# service docker stop

[root@localhost ~]# ip link set dev docker0 down

[root@localhost ~]# brctl delbr docker0

创建一个网桥

[root@localhost ~]# brctl addbr bridge0

[root@localhost ~]# ip addr add 192.168.5.1/24 dev bridge0

[root@localhost ~]# ip link set dev bridge0 up

查看新建的网桥

[root@localhost ~]# ip addr show bridge0

231: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 

    link/ether 7a:7b:a6:44:4e:eb brd ff:ff:ff:ff:ff:ff

    inet 192.168.5.1/24 scope global bridge0

       valid_lft forever preferred_lft forever

    inet6 fe80::787b:a6ff:fe44:4eeb/64 scope link 

       valid_lft forever preferred_lft forever



配置 Docker 服务,默认桥接到创建的网桥上。


[root@localhost ~]# echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker

[root@localhost ~]# service docker start


启动 Docker 服务。 新建一个容器,可以看到它已经桥接到了 bridge0 上。


在容器中可以使用 ip addr 和 ip route 命令来查看 IP 地址配置和路由信息。


*工具

pipework

Jérôme Petazzoni 编写了一个叫 pipework 的 shell 脚本,可以帮助用户在比较复杂的场景中完成容器的连接。


playground

Brandon Rhodes 创建了一个提供完整的 Docker 容器网络拓扑管理的 Python库,包括路由、NAT 防火墙;以及一些提供 HTTP, SMTP, POP, IMAP, Telnet, SSH, FTP 的服务器。


5>配置固定ip,不是公网ip,docker不能配置公网ip

http://www.xiaomastack.com/2015/02/06/docker-static-ip/



6>点对点连接



5,实 例

1>通过supervisor来管理进程

Dockerfile配置

[root@localhost dockerfile]# cat Dockerfile 

FROM centos:6.6

MAINTAINER duxuefeng@oasgames.com

RUN yum -y update


RUN yum install -y openssh-server nginx supervisor

#官方源是没有nginx和supervisor的,需要执行完Dockerfile后进入交互模式安装,后commit。

|--------------------------------------------------------------------------------------------

|[root@de8aff6c9df4 /]# cat /etc/yum.repos.d/nginx.repo 

|[nginx]  

|name=nginx repo  

|baseurl=http://nginx.org/packages/centos/$releasever/$basearch/  

|gpgcheck=0  

|enabled=1

|

|yum install nginx -y

|

|#配置supervisor

|yum install python-setuptools

|easy_install supervisor

|-------------------------------------------------------------------------------------------

RUN mkdir -p /var/run/sshd

RUN mkdir /var/log/supervisor


COPY supervisord.conf /etc/supervor/conf.d/supervisord.conf

|--------------------------------------------------------------------------------------

|#supervisord.conf

|[supervisord]

|nodaemon=true

|[program:sshd]

|command=/usr/sbin/sshd -D

|

|[program:nginx]

|command=/usr/sbin/nginx -c /etc/nginx/nginx.conf

---------------------------------------------------------------------------------------

EXPOSE 22 80

CMD ["/usr/bin/supervisord"]


#使用

非交互模式

docker run -d -p 22 -p 80  duxuefeng/supervisor:3.0  /usr/bin/supervisord -c /etc/supervor/conf.d/supervisord.conf


交互模式

docker run -d -p 22 -p 80  duxuefeng/supervisor:3.0





-------------------------------------------------------------------------------------

docker run 命令

docker run [OPTIONS] IMAGE[:TAG][COMMAND][ARG...]

OPTIONS分为两类

1,设定操作执行方式

+1,设定container的运行方式,前台还是后台执行

+2,设定container的id

+3,设定network参数

+4,设定container的cpu和内存参数

+5,设定权限和LXC参数

2,设定image的默认资源


Usage: docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]  

Run a command in a new container  

-a=map[]: 附加标准输入、输出或者错误输出  

-c=0: 共享CPU格式(相对重要)  

-cidfile="": 将容器的ID标识写入文件  

-d=false: 分离模式,在后台运行容器,并且打印出容器ID  

-e=[]:设置环境变量  

-h="": 容器的主机名称  

-i=false: 保持输入流开放即使没有附加输入流  

-privileged=false: 给容器扩展的权限  

-m="": 内存限制 (格式:<number><optional unit>, unit单位 = b, k, m or g)  

-n=true: 允许镜像使用网络  

-p=[]: 匹配镜像内的网络端口号  

-rm=false:当容器退出时自动删除容器 (不能跟 -d一起使用)  

-t=false: 分配一个伪造的终端输入  

-u="": 用户名或者ID  

-dns=[]: 自定义容器的DNS服务器  

-v=[]: 创建一个挂载绑定:[host-dir]:[container-dir]:[rw|ro].如果容器目录丢失,docker会创建一个新的卷  

-volumes-from="": 挂载容器所有的卷  

-entrypoint="": 覆盖镜像设置默认的入口点  

-w="": 工作目录内的容器  

-lxc-conf=[]: 添加自定义-lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" 

-sig-proxy=true: 代理接收所有进程信号(even in non-tty mode)  

-expose=[]: 让你主机没有开放的端口  

-link="": 连接到另一个容器(name:alias)  

-name="": 分配容器的名称,如果没有指定就会随机生成一个  

-P=false: Publish all exposed ports to thehost interfaces 公布所有显示的端口主机接口



1,设定操作执行方式

++设定运行方式

-d:加上该参数确定这个容器是在后台运行。反之在前台运行,container的所有输出都可以在当前窗口中看到

+-a=[],指定挂载标准数据流,‘STDIN’,‘STDOUT’,‘STDERR’

+-i -t ,对于执行容器内的交互操作,例如,shell脚本,我们必须使用-i -t申请一个控制台同容器进行数据交互。

docker run -a stdin -a stdout -i -t ubuntu /bin/bash

+但是当通过管道同容器交互就不能使用-t,如:echo test | run -i busybox cat   



-p 指定container绑定到宿主机的端口,-P从49153-65535中随机分配未被占用的端口绑定到宿主机上。--link container间内网访问


++设定id

+给container命名有三种方式:

1,使用uuid长命名,提交副本时产生的uuid。

2,使用uuid短命名,  IMAGE ID。

3,使用name,docker images中的REPOSITORY


+当运行docker时有自动化要求,可以要求docker将ID输出到指定的文件中,方便后续操作,--cidfile=“”



++IPC设定

默认情况先,所有容器都开启了IPC命名空间。共享那次可以提高进程数据的交互速度。


++网络设定

默认情况下所有的container都开启了网络接口,同时可以接受任何外部数据的请求。

+--dns,默认情况下,container使用host的DNS设置,通过--dns来覆盖container内的dns的设置。

+--net=""

none:关闭container内的网络连接,内部只会有一个lookback接口。

bridge:默认选项,通过veth接口来连接

host:允许container使用host的网络堆栈信息

container:使用另一个container的网络堆栈信息


+--add-host="",动态向container中的/etc/hosts添加hostname信息


clean up

--rm ,需要短期运行一个前台container,产生的数据不需要保留,在使用完毕之后自动清理产生的数据。


安全配置

--security-opt


cpu和内存的配置


-m="",调整内存。

-c="", 调整cpu优先级。默认情况下所有的container享有相同的cpu优先级和cpu调度周期。-c="0"表示赋予当前container 1024个cpu共享周期。比如说:-c="0"启动c0,-c="512"启动c1,这时c0可以使用100%的cpu资源,c1可以使用50%的cpu资源。



runtime privilege  linux capabilities  LXC configuration

--privileged 加上该参数后,docker可以访问宿主机所有设备的权限。

--device=[],默认情况下,container对设备的读,写,创建设备文件的权限,使用:rwm来配合--device,控制这些权限。

docker run --device=/dev/sda:/dev/xvdc:rwm --rm -it centos fidsk /dev/xvdc

--cap-add/--cap-drop,配合--privileged,你可以更细致的控制container,默认使用这两个参数的情况下,可以有修改内核的权限,

例如:如果想让某个container拥有除了MKNOD之外的所有内核权限:docker run --cap-add=ALL --cap-drop=MKNOD

      如果需要修改网络接口数据:docker run --cap-add=NET_ADMIN centos ip link add dummy0 type dummy

      如果要挂载FUSE文件系统:docker run --cap-add SYS_ADMIN --device /dev/fuse sshfs


-v 当docker创建一个数据卷并挂载到容器中时使用-v来标记。

例如:docker -v /opt/app:/home/app -p 80:8000 -d --name centos



2,设定image的默认资源,也就是image使用者可以用此命令来覆盖image开发者在build阶段所设定的默认值

当开发者使用dockerfile进行build或者commit时,开发者可以设定一些image参数。这些参数有四个无法进行覆盖:FROM,MAINTARNER,RUN,ADD,其余参数都可以通过docker run进行覆盖。

+cmd,可选,可用用新命令覆盖旧命令

+--entrypoint="",指定当container执行时,需要启动那些进程。

例子:docker run -i -t --entrypoint /bin/bash  example/redis -c ls -l


+--expose,dockerfile在网络方面除了提供一个expose之外,没有提供其他选项。

-p 指定container绑定到宿主机的端口,-P从49153-65535中随机分配未被占用的端口绑定到宿主机上。--link container间内网访问


+ENV

当container启动时,会自动在contarner中初始化变量:HOME,HOSTNAME,PATH,TERM。

可以通过-e来设定任意的环境变量,甚至覆盖原有的环境变量,或者是在dockerfile中通过ENV设定的环境变量。


+volume

设置共享文件系统


+user

container中默认的用户是root,-u,来覆盖默认用户


+workdir

container中默认的工作目录是根目录,-w,来覆盖默认工作目录。


+++++++++++++++++++++++++++++++++++++++++++++++++++++++

dockerfile讲解

[root@localhost centos7]# cat Dockerfile 

#

# MAINTAINER        Carson,C.J.Zeong <zcy@nicescale.com>

# DOCKER-VERSION    1.6.2

#

# Dockerizing CentOS7: Dockerfile for building CentOS images

#

FROM       centos:centos7.1.1503     #基础镜像也就是父镜像,docker-hub上pull下来

MAINTAINER Carson,C.J.Zeong <zcy@nicescale.com>   #维护者信息


ENV TZ "Asia/Shanghai"  #设置时区环境变量

ENV TERM xterm          #


#ADD和copy都是复制文件,add比copy多了两个功能,1,被拷贝可以是链接地址,2,可以是压缩文件,拷贝到目的地后自动解压

ADD aliyun-mirror.repo /etc/yum.repos.d/CentOS-Base.repo

ADD aliyun-epel.repo /etc/yum.repos.d/epel.repo


#docker每执行一条命令都生成docker镜像的一层,docker镜像是分层的

RUN yum install -y curl wget tar bzip2 unzip vim-enhanced passwd sudo yum-utils hostname net-tools rsync man && \

    yum install -y gcc gcc-c++ git make automake cmake patch logrotate python-devel libpng-devel libjpeg-devel && \

    yum install -y --enablerepo=epel pwgen python-pip && \

    yum clean all


#安装服务

RUN pip install supervisor

ADD supervisord.conf /etc/supervisord.conf


RUN mkdir -p /etc/supervisor.conf.d && \

    mkdir -p /var/log/supervisor


#映射端口,宿主机随机匹配一个端口映射到22端口

EXPOSE 22

#docker每次启动的时候需要执行的命令

ENTRYPOINT ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]


[root@localhost centos7]# docker build -t csphere/centos:7.1 .

#-t 名字

#最后加dockerfile的路径




CM和ENTRYPOINT的区别


Dockerfile 用于自动化构建一个docker镜像。Dockerfile里有 CMD 与 ENTRYPOINT 两个功能咋看起来很相似的指令,开始的时候觉得两个互用没什么所谓,但其实并非如此:


CMD指令:


The main purpose of a CMD is to provide defaults for an executing container.


CMD在容器运行的时候提供一些命令及参数,用法如下:


CMD ["executable","param1","param2"] (exec form, this is the preferred form) 

CMD ["param1","param2"] (as default parameters to ENTRYPOINT) 

CMD command param1 param2 (shell form) 

第一种用法:运行一个可执行的文件并提供参数。

第二种用法:为ENTRYPOINT指定参数。

第三种用法(shell form):是以”/bin/sh -c”的方法执行的命令。

如你指定:


CMD [“/bin/echo”, “this is a echo test ”] 

build后运行(假设镜像名为ec):


docker run ec 

就会输出: this is a echo test


是不是感觉很像开机启动项,你可以暂时这样理解。


注意点:


docker run命令如果指定了参数会把CMD里的参数覆盖: (这里说明一下,如:docker run -it ubuntu /bin/bash 命令的参数是指/bin/bash 而非 -it ,-it只是docker 的参数,而不是容器的参数,以下所说参数均如此。)


同样是上面的ec镜像启动:


docker run ec /bin/bash


就不会输出:this is a echo test,因为CMD命令被”/bin/bash”覆盖了。


ENTRYPOINT  


字面意思是进入点,而它的功能也恰如其意。


An ENTRYPOINT allows you to configure a container that will run as an executable.它可以让你的容器功能表现得像一个可执行程序一样。


容器功能表现得像一个可执行程序一样,这是什么意思呢?


直接给个例子好说话:


例子一:


使用下面的ENTRYPOINT构造镜像:


ENTRYPOINT ["/bin/echo"] 

那么docker build出来的镜像以后的容器功能就像一个/bin/echo程序:


比如我build出来的镜像名称叫imageecho,那么我可以这样用它:


docker run -it imageecho “this is a test” 

这里就会输出”this is a test”这串字符,而这个imageecho镜像对应的容器表现出来的功能就像一个echo程序一样。 你添加的参数“this is a test”会添加到ENTRYPOINT后面,就成了这样 /bin/echo “this is a test” 。现在你应该明白进入点的意思了吧。


例子二:


ENTRYPOINT ["/bin/cat"]


构造出来的镜像你可以这样运行(假设名为st):


docker run -it st /etc/fstab 

这样相当: /bin/cat /etc/fstab 这个命令的作用。运行之后就输出/etc/fstab里的内容。


ENTRYPOINT有两种写法:


写法一:


ENTRYPOINT ["executable", "param1", "param2"] (the preferred exec form) 

写法二:


ENTRYPOINT command param1 param2 (shell form) 

你也可以在docker run 命令时使用–entrypoint指定(但是只能用写法一)。


下面是我把ENTRYPOINT设为[“/bin/sh -c”]时候运行的情况:


linux-oj9e:/home/lfly/project/docker # docker run -it t2 /bin/bash 

root@4c8549e7ce3e:/# ps 

PID TTY TIME CMD 

1 ? 00:00:00  sh 

9 ? 00:00:00  bash 

19 ? 00:00:00  ps 

可以看到PID为1的进程运行的是sh,而bash只是sh的一个子进程,/bin/bash只是作为 /bin/sh -c后面的参数。


CMD可以为ENTRYPOINT提供参数,ENTRYPOINT本身也可以包含参数,但是你可以把那些可能需要变动的参数写到CMD里而把那些不需要变动的参数写到ENTRYPOINT里面例如:


FROM ubuntu:14.10  

ENTRYPOINT ["top", "-b"]   

CMD ["-c"]  

把可能需要变动的参数写到CMD里面。然后你可以在docker run里指定参数,这样CMD里的参数(这里是-c)就会被覆盖掉而ENTRYPOINT里的不被覆盖。


注意点1:


ENTRYPOINT有两种写法,第二种(shell form)会屏蔽掉docker run时后面加的命令和CMD里的参数。


注意点2:


网上有资料说ENTRYPOINT的默认值是[”/bin/sh -c”],但是笔者在试验的时候得到的结果并不是这样的。


笔者使用ENTRYPOINT [“/bin/sh -c”] 指令构造一个以/bin/sh -c为进入点的镜像,命名为sh,然后我可以这样运行:


docker run -it sh “while(ture ) do echo loop; done” 

运行结果就是无限输出loop。但如果直接运行一个ubuntu:14.10镜像,情况不是这样的:


docker run -it ubuntu:14.10 “while(ture ) do echo loop; done” 

得到这样的错误:


linux-oj9e:/home/lfly # docker run -it ubuntu:14.10 “while(true) do echo this; done” 2014/11/16 18:07:53 Error response from daemon: Cannot start container 4bfe9c6faeec3ed465788a201a2f386cb1af35aba197dbc78b87c0d5dda1f88e: exec: “while(true) do echo this; done”: executable file not found in $PATH 

可以猜想默认情况下ENTRYPOINT并不是[“/bin/sh -c”]。


而且直接运行ubuntu:14.10列出程序也可以看到PID为1的程序并不是sh。所以更否定了网友的说法,ENTRYPOINT并不默认为[“/bin/sh -c”] 。


-------------------------------------------------------

docker命令

搜索镜像

#docker search centos6


安装镜像

#docker pull treasureboat/centos6


查看安装的镜像

#docker images   


删除一个镜像

#docker rmi centos7


查看一个镜像的历史

#docker history centos7啊


运行容器的shell界面

# docker run -i -t docker.cn/docker/centos:centos6 /bin/bash



删除一个容器

#docker rm name/id


停止、启动、杀死一个容器  

#docker stop Name/ID  

#docker start Name/ID  

#docker kill Name/ID  


从一个容器中取日志

#docker diff Name/ID


显示一个运行的容器里面的进程信息

#docker top Name/ID



从容器里面拷贝文件/目录到本地一个路径  

#docker cp Name:/container_path to_path  

#docker cp ID:/container_path to_path 


重启一个正在运行的容器

#docker restart Name/ID  



退出再进

#docker exec -it websit /bin/bash




------------------------------------

渗透执行


如果想通过ssh进入container,需要安装nsenter,安装步骤如下:

wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz

tar -zxf-cd util-linux-2.24

./configure –without-ncurses

make

cp nsenter /usr/local/bin/

这个地方有个坑,之前我写的是make && make install,经阿里云的技术团队测试,make之后千万不能make install,make install后会替代操作系统底层的一些东西,直接影响linux操作系统的启动,在阿里云上会导致ubuntu14.0.4不能启动,其实只需要把nsenter 复制到/usr/local/bin目录下即可。国内其他文档介绍安装nsenter的时候都没说明这些,在此特别写篇博客记录一下。

找到mysql容器的第一个进程的pid

pid=`docker inspect --format "{{ .State.pid }}" mysql_1 `

然后渗入(需要root权限)

sudo nsenter --target $PID --mount --uts --ipc --net --pid


展开阅读全文
打赏
0
6 收藏
分享
加载中
更多评论
打赏
0 评论
6 收藏
0
分享
返回顶部
顶部