使用Docker已有一段时间了,今天正好有空梳理下自己平时操作Docker时的一些命令和注意细节:
Docker 命令帮助
$ sudo docker
Commands:
attach Attach to a running container
--将终端依附到容器上
1> 运行一个交互型容器
[root@localhost ~]# docker run -i -t centos /bin/bash
[root@f0a02b473067 /]#
2> 在另一个窗口上查看该容器的状态
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4a75f165ce6 centos "/bin/bash" 5 seconds ago Up 5 seconds cranky_mahavira
3> 退出第一步中运行的容器
[root@d4a75f165ce6 /]# exit
exit
4> 查看该容器的状态
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4a75f165ce6 centos "/bin/bash" 2 minutes ago Exited (0) 23 seconds ago cranky_mahavira
可见此时容器的状态是Exited,那么,如何再次运行这个容器呢?可以使用docker start命令
5> 再次运行该容器
[root@localhost ~]# docker start cranky_mahavira
cranky_mahavira
6> 再次查看该容器的状态
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4a75f165ce6 centos "/bin/bash" 6 minutes ago Up 29 seconds cranky_mahavira
因为该容器是交互型的,但此刻我们发现没有具体的终端可以与之交互,这时可使用attach命令。
7> 通过attach命令进行交互
[root@localhost ~]# docker attach cranky_mahavira
[root@d4a75f165ce6 /]#
build Build an image from a Dockerfile
--通过Dockerfile创建镜像
commit Create a new image from a container's changes
--通过容器创建本地镜像
注意:如果是要push到docker hub中,注意生成镜像的命名
[root@localhost ~]# docker commit centos_v1 centos:v1
68ad49c999496cff25fdda58f0521530a143d3884e61bce7ada09bdc22337638
[root@localhost ~]# docker push centos:v1
You cannot push a "root" repository. Please rename your repository to <user>/<repo> (ex: <user>/centos)
用centos:v1就不行,因为它push到docker hub中时,是推送到相应用户下,必须指定用户名。譬如我的用户名是ivictor,则新生成的本地镜像命名为:
docker push victor/centos:v1,其中v1是tag,可不写,默认是latest
cp Copy files/folders from a container to a HOSTDIR or to STDOUT
--在宿主机和容器之间相互COPY文件
cp的用法如下:
Usage: docker cp [OPTIONS] CONTAINER:PATH LOCALPATH|-
docker cp [OPTIONS] LOCALPATH|- CONTAINER:PATH
如:容器mysql中/usr/local/bin/存在docker-entrypoint.sh文件,可如下方式copy到宿主机
# docker cp mysql:/usr/local/bin/docker-entrypoint.sh /root
修改完毕后,将该文件重新copy回容器
# docker cp /root/docker-entrypoint.sh mysql:/usr/local/bin/
create Create a new container
--创建一个新的容器,注意,此时,容器的status只是Created
diff Inspect changes on a container's filesystem
--查看容器内发生改变的文件,以我的mysql容器为例
[root@localhost ~]# docker diff mysqldb
C /root
A /root/.bash_history
A /test1.txt
A /test.tar
A /test.txt
C /run
C /run/mysqld
A /run/mysqld/mysqld.pid
A /run/mysqld/mysqld.sock
不难看出,C对应的均是目录,A对应的均是文件
events Get real time events from the server
--实时输出Docker服务器端的事件,包括容器的创建,启动,关闭等。
譬如:
[root@localhost ~]# docker events
2015-09-08T17:40:13.000000000+08:00 d2a2ef5ddb90b505acaf6b59ab43eecf7eddbd3e71f36572436c34dc0763db79: (from wordpress) create
2015-09-08T17:40:14.000000000+08:00 d2a2ef5ddb90b505acaf6b59ab43eecf7eddbd3e71f36572436c34dc0763db79: (from wordpress) die
2015-09-08T17:42:10.000000000+08:00 839866a338db6dd626fa8eabeef53a839e4d2e2eb16ebd89679aa722c4caa5f7: (from mysql) start
exec Run a command in a running container
--用于容器启动之后,执行其它的任务
通过exec命令可以创建两种任务:后台型任务和交互型任务
后台型任务:docker exec -d cc touch 123 其中cc是容器名
交互型任务:
[root@localhost ~]# docker exec -i -t cc /bin/bash
root@1e5bb46d801b:/# ls
123 bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
export Export a container's filesystem as a tar archive
--将容器的文件系统打包成tar文件
有两种方式(mysqldb为容器名):
docker export -o mysqldb1.tar mysqldb
docker export mysqldb > mysqldb.tar
history Show the history of an image
--显示镜像制作的过程,相当于dockfile
images List images
--列出本机的所有镜像
import Import the contents from a tarball to create a filesystem image
--根据tar文件的内容新建一个镜像,与之前的export命令相对应
[root@localhost ~]# docker import mysqldb.tar mysql:v1
eb81de183cd94fd6f0231de4ff29969db822afd3a25841d2dc9cf3562d135a10
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql v1 eb81de183cd9 21 seconds ago 281.9 MB
Docker option
Usage of docker:
--api-enable-cors=false Enable CORS headers in the remote API # 远程 API 中开启 CORS 头
-b, --bridge="" Attach containers to a pre-existing network bridge # 桥接网络
use 'none' to disable container networking
--bip="" Use this CIDR notation address for the network bridge's IP, not compatible with -b
# 和 -b 选项不兼容,具体没有测试过
-d, --daemon=false Enable daemon mode # daemon 模式
-D, --debug=false Enable debug mode # debug 模式
--dns=[] Force docker to use specific DNS servers # 强制 docker 使用指定 dns 服务器
--dns-search=[] Force Docker to use specific DNS search domains # 强制 docker 使用指定 dns 搜索域
-e, --exec-driver="native" Force the docker runtime to use a specific exec driver # 强制 docker 运行时使用指定执行驱动器
--fixed-cidr="" IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)
this subnet must be nested in the bridge subnet (which is defined by -b or --bip)
-G, --group="docker" Group to assign the unix socket specified by -H when running in daemon mode
use '' (the empty string) to disable setting of a group
-g, --graph="/var/lib/docker" Path to use as the root of the docker runtime # 容器运行的根目录路径
-H, --host=[] The socket(s) to bind to in daemon mode # daemon 模式下 docker 指定绑定方式[tcp or 本地 socket]
specified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.
--icc=true Enable inter-container communication # 跨容器通信
--insecure-registry=[] Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback) (e.g., localhost:5000 or 10.20.0.0/16)
--ip="0.0.0.0" Default IP address to use when binding container ports # 指定监听地址,默认所有 ip
--ip-forward=true Enable net.ipv4.ip_forward # 开启转发
--ip-masq=true Enable IP masquerading for bridge's IP range
--iptables=true Enable Docker's addition of iptables rules # 添加对应 iptables 规则
--mtu=0 Set the containers network MTU # 设置网络 mtu
if no value is provided: default to the default route MTU or 1500 if no default route is available
-p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file # 指定 pid 文件位置
--registry-mirror=[] Specify a preferred Docker registry mirror
-s, --storage-driver="" Force the docker runtime to use a specific storage driver # 强制 docker 运行时使用指定存储驱动
--selinux-enabled=false Enable selinux support # 开启 selinux 支持
--storage-opt=[] Set storage driver options # 设置存储驱动选项
--tls=false Use TLS; implied by tls-verify flags # 开启 tls
--tlscacert="/root/.docker/ca.pem" Trust only remotes providing a certificate signed by the CA given here
--tlscert="/root/.docker/cert.pem" Path to TLS certificate file # tls 证书文件位置
--tlskey="/root/.docker/key.pem" Path to TLS key file # tls key 文件位置
--tlsverify=false Use TLS and verify the remote (daemon: verify client, client: verify daemon) # 使用 tls 并确认远程控制主机
-v, --version=false Print version information and quit
Docker run指令
[root@localhost ~]# docker run --help
: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
--add-host=[] Add a custom host-to-IP mapping (host:ip) 增加一个定制的'主机-IP'映射
--blkio-weight=0 Block IO (relative weight), between 10 and 1000
-c, --cpu-shares=0 CPU shares (relative weight)
--cap-add=[] Add Linux capabilities 增加linux能力
--cap-drop=[] Drop Linux capabilities
--cgroup-parent= Optional parent cgroup for the container
--cidfile= Write the container ID to the file 把容器的ID写入文件
--cpu-period=0 Limit CPU CFS (Completely Fair Scheduler) period
--cpu-quota=0 Limit the CPU CFS quota
--cpuset-cpus= CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems= MEMs in which to allow execution (0-3, 0,1)
-d, --detach=false Run container in background and print container ID 在后台运行容器并打印容器ID
--device=[] Add a host device to the container 把一个主机设备添加到容器
--dns=[] Set custom DNS servers 设置定制的域名服务器
--dns-search=[] Set custom DNS search domains 设置定制的域名服务器的搜索域
-e, --env=[] Set environment variables 设置环境变量
--entrypoint= Overwrite the default ENTRYPOINT of the image 覆盖镜像的默认进入点
--env-file=[] Read in a file of environment variables 读入一个包含环境变量的文件
--expose=[] Expose a port or a range of ports 暴露一个端口、端口范围
-h, --hostname= Container host name 容器的主机名
-i, --interactive=false Keep STDIN 标准输入
--ipc= IPC namespace to use 使用的IPC命名空间
--pid= PID namespace to use 使用的PID命名空间
--uts= UTS namespace to use
-l, --label=[] Set meta data on a container 在容器上,设置元数据
--label-file=[] Read in a line delimited file of labels
--link=[] Add link to another container 添加一个到另一个容器的连接
--log-driver= Logging driver for container 容器的日志驱动
--log-opt=[] Log driver options
--lxc-conf=[] Add custom lxc options 添加定制的lxc选项
-m, --memory= Memory limit 内存限制
--mac-address= Container MAC address (e.g. 92:d0:c6:0a:29:33) 容器的MAC地址
--memory-swap= Total memory (memory + swap), '-1' to disable swap 容器的总内存(物理内容+交换区)
--name= Assign a name to the container 为容器分配一个名字
--net=bridge Set the Network mode for the container 为容器设置网络模式
--oom-kill-disable=false Disable OOM Killer
-P, --publish-all=false Publish all exposed ports to random ports 把通气端口发布的主机。即容器端口映射到宿主机的任意端口上。
-p, --publish=[] Publish a container's port(s) to the host 把容器的端口发布到主机,即容器端口映射到宿主机的具体端口上。可加上多个-p
--privileged=false Give extended privileges to this container 赋予容器扩展权限
--read-only=false Mount the container's root filesystem as read only 以只读的方式装载容器的根文件系统
--restart=no Restart policy to apply when a container exits
--rm=false Automatically remove the container when it exits 当容器存在时,自动移除容器
--security-opt=[] Security Options 安全选项
--sig-proxy=true Proxy received signals to the process
-t, --tty=false Allocate a pseudo-TTY 分配一个伪终端
-u, --u-user= Username or UID (format: <name|uid>[:<group|gid>])
--ulimit=[] Ulimit options
-v, --volume=[] Bind mount a volume
--volumes-from=[] Mount volumes from the specified container(s)
-w, --workdir= Working directory inside the container
--------------------------------------------
当运行docker run命令时,Docker会启动一个进程,并为这个进程分配其独占的文件系统、网络资源和以此进程为根进程的进程组。
在容器启动时,镜像可能已经定义了要运行的二进制文件、暴露的网络端口等,但是用户可以通过docker run命令重新定义(docker run可以控制一个容器运行时的行为,它可以覆盖docker build在构建镜像时的一些默认配置),这也是为什么run命令相比于其它命令有如此多的参数的原因。
使用方法:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS总起来说可以分为两类:
a)设置运行方式:
决定容器的运行方式,前台执行还是后台执行;
设置containerID;
设置网络参数;
设置容器的CPU和内存参数;
设置权限和LXC参数;
b)设置镜像的默认资源,也就是说用户可以使用该命令来覆盖在镜像构建时的一些默认配置。
docker run [OPTIONS]可以让用户完全控制容器的生命周期,并允许用户覆盖执行docker build时所设定的参数,甚至也可以修改本身由Docker所控制的内核级参数。
Operator exclusive options
当执行docker run时可以设置以下参数:
1.Detached vs Foreground
Detached (-d)
- Foreground
2.Container Identification
Name (--name)
- PID Equivalent
3.IPC Setting
4.Network Settings
5.Clean Up (--rm)
6.Runtime Constraints on CPU and Memory
7.Runtime Privilege, Linux Capabilities, and LXC Configuration
----------------------------------------------------------------------------------------------
1.Detached vs foreground
当我们启动一个容器时,首先需要确定这个容器是运行在前台还是运行在后台。
-d=false, 没有附加标准输入、输出、错误 ---- 运行在后台
Detached (-d)
docker run -d
-d=false
--detach=false
那么容器将会运行在后台模式。
此时所有I/O数据只能通过网络资源或者共享卷组来进行交互,因为容器不再监听你执行docker run的这个终端命令行窗口。
但你可以通过执行docker attach来重新附着到该容器的回话中。
需要注意的是,容器运行在后台模式下,是不能使用--rm选项的。
2.Foregroud
不指定-d参数(为明确给-d选项指定值,取默认值false) --在前台模式下
Docker会在容器中启动进程,同时将当前的命令行窗口附着到容器的标准输入、标准输出和标准错误中 --- 把当前的命令行窗口附着到容器的标准输入、输出、错误上.
也就是说容器中所有的输出都可以在当前窗口中看到。甚至它都可以虚拟出一个TTY窗口,来执行信号中断。
这一切都是可以配置的:
-a=[], --attach=[] 把容器的标准输入、输出、错误附着到当前的命令行窗口
-t=false, --tty=false 分配一个伪终端
-i=false, --interactive=false 附着标准输入到当前命令行
-------特别注意---------
注意:
-i 选项取默认值(false)
docker run 没有-i选项,相当于docker run -i=false,即非交互式运行
docker run -i 指定-i选项,即以交互式运行
如果在执行run命令时没有指定-a参数,那么Docker默认会挂载所有标准数据流,包括输入输出和错误,你可以单独指定挂载哪个标准流。
# docker run -a=[stdin, stdout] -i -t ubuntu /bin/bash
如果要进行交互式操作(例如Shell脚本),那我们必须使用-i -t参数同容器进行数据交互。
但是当通过管道同容器进行交互时,就不需要使用-t参数,例如下面的命令:
# echo test | docker run -i busybox cat
Docker容器识别
1.Name(--name)
可以通过三种方式为容器命名:
1)使用UUID长命名("f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778")
2)使用UUID短命令("f78375b1c487")
3)使用Name("evil_ptolemy")
这个UUID标示是由Docker deamon生成的。
如果你在执行docker run时没有指定--name,那么deamon会自动生成一个随机字符串UUID。
但是对于一个容器来说有个name会非常方便,当你需要连接其它容器时或者类似需要区分其它容器时,使用容器名称可以简化操作。无论容器运行在前台或者后台,这个名字都是有效的。
PID equivalent
如果在使用Docker时有自动化的需求,你可以将containerID输出到指定的文件中(PIDfile),类似于某些应用程序将自身ID输出到文件中,方便后续脚本操作。
--cidfile="": Write the container ID to the file
2.Image[:tag]
当一个镜像的名称不足以分辨这个镜像所代表的含义时,你可以通过tag将版本信息添加到run命令中,以执行特定版本的镜像。例如:docker run ubuntu:14.04
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/uifd/ui-for-docker latest 312812aadc64 34 hours ago 8.096 MB
docker.io/nginx latest 5e69fe4b3c31 5 days ago 182.5 MB
192.168.1.23:5000/tomcat7 latest 47c5123914a1 6 days ago 562.3 MB
docker.io/ubuntu latest 0ef2e08ed3fa 4 weeks ago 130 MB
docker.io/centos latest 67591570dd29 3 months ago 191.8 MB
docker.io/tomcat latest ebb17717bed4 5 months ago 355.4 MB
3.IPC Settings
默认情况下,所有容器都开启了IPC命名空间。
--ipc="" : Set the IPC mode for the container,
'container:<name|id>': reuses another container's IPC namespace
'host': use the host's IPC namespace inside the container
IPC(POSIX/SysV IPC)命名空间提供了相互隔离的命名共享内存、信号灯变量和消息队列。
共享内存可以提高进程数据的交互速度。
共享内存一般用在数据库和高性能应用(C/OpenMPI、C++/using boost libraries)上或者金融服务上。
如果需要容器中部署上述类型的应用,那么就应该在多个容器直接使用共享内存了。
----------------------------------------------------------------------------------------------
Network settings
默认情况下,所有的容器都开启了网络接口,同时可以接受任何外部的数据请求。
--dns=[] : Set custom dns servers for the container
--net="bridge" : Set the Network mode for the container
##在docker桥接上,为容器创建一个新的网络栈
'bridge' : creates a new network stack for the container on the docker bridge
'none' : no networking for this container 没有为该容器配置网络
'container:<name|id>' : reuses another container network stack 重用另一个容器的网络栈
'host' : use the host network stack inside the container 在容器内使用主机的网络栈
--add-host="" : Add a line to /etc/hosts (host:IP) 向容器/etc/hosts的文件中增加一行
--mac-address="" : Sets the container's Ethernet device's MAC address 设置容器网卡的MAC地址
你可以通过docker run --net=none来关闭网络接口,此时将关闭所有网络数据的输入输出,你只能通过STDIN、STDOUT或者files来完成I/O操作。
默认情况下,容器使用主机的DNS设置,你也可以通过--dns来覆盖容器内的DNS设置。
同时Docker为容器默认生成一个MAC地址,你可以通过--mac-address 12:34:56:78:9a:bc来设置你自己的MAC地址。
Docker支持的网络模式有:
none 关闭容器内的网络连接
bridge 通过veth接口来连接容器,默认配置。
host 允许容器使用host的网络堆栈信息。注意:这种方式将允许容器访问host中类似D-BUS之类的系统服务,所以认为是不安全的。
container 使用另外一个容器的网络堆栈信息。
----None模式----
将网络模式设置为none时,这个容器将不允许访问任何外部router。
这个容器内部只会有一个loopback接口,而且不存在任何可以访问外部网络的router。
-----Bridge模式-----
Docker默认会将容器设置为bridge模式。
此时在主机上面将会存在一个docker0的网络接口,同时会针对容器创建一对veth接口。
其中一个veth接口是在主机充当网卡桥接作用,另外一个veth接口存在于容器的命名空间中,并且指向容器的loopback。
Docker会自动给这个容器分配一个IP,并且将容器内的数据通过桥接转发到外部。
-----Host模式-----
当网络模式设置为host时,这个容器将完全共享host的网络堆栈。
host所有的网络接口将完全对容器开放。
容器的主机名也会存在于主机的hostname中。
这时,容器所有对外暴露的端口和对其它容器的连接,将完全失效。
-----Container模式-----
当网络模式设置为Container时,这个容器将完全复用另外一个容器的网络堆栈。同时使用时这个容器的名称必须要符合下面的格式:--net container:<name|id>.
比如当前有一个绑定了本地地址localhost的Redis容器。
如果另外一个容器需要复用这个网络堆栈, 则需要如下操作:
# docker run -d --name redis example/redis --bind 127.0.0.1
//use the redis container's network stack to access localhost
# docker run --rm -ti --net container:redis example/redis-cli -h 127.0.0.1
管理/etc/hosts
/etc/hosts文件中会包含容器的hostname信息,我们也可以使用--add-host这个参数来动态添加/etc/hosts中的数据。
# docker run -ti --add-host db-static:86.75.30.9 ubuntu cat /etc/hosts
172.17.0.22 09d03f76bf2c
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
86.75.30.9 db-static ##容器启动时添加进来的 地址到主机名映射
----------------------------------------------------------------------------------------------
Clean up
默认情况下,每个容器在退出时,它的文件系统也会保存下来,这样一方面调试会方便些,因为你可以通过查看日志等方式来确定最终状态。
另外一方面,你也可以保存容器所产生的数据。
但是当你仅仅需要短暂的运行一个容器,并且这些数据不需要保存,你可能就希望Docker能在容器结束时自动清理其所产生的数据。
这个时候你就需要--rm这个参数了。
<<<<<< 注意:--rm 和 -d不能共用 >>>>>>
--rm=false: Automatically remove the container when it exits (incompatible with -d)
Security configuration
--security-opt="label:user:USER" : Set the label user for the container
--security-opt="label:role:ROLE" : Set the label role for the container
--security-opt="label:type:TYPE" : Set the label type for the container
--security-opt="label:level:LEVEL" : Set the label level for the container
--security-opt="label:disable" : Turn off label confinement for the container 关闭容器的标签限制
--secutity-opt="apparmor:PROFILE" : Set the apparmor profile to be applied to the container
你可以通过--security-opt修改容器默认的schema标签。
比如说,对于一个MLS系统来说(译者注:MLS应该是指Multiple Listing System),你可以指定MCS/MLS级别。
使用下面的命令可以在不同的容器间分享内容:
# docker run --security-opt=label:level:s0:c100,c200 -i -t fedora bash
如果是MLS系统,则使用下面的命令:
# docker run --security-opt=label:level:TopSecret -i -t rhel7 bash
使用下面的命令可以在容器内禁用安全策略:
# docker run --security-opt=label:disable -i -t fedora bash
如果你需要在容器内执行更为严格的安全策略,那么你可以为这个容器指定一个策略替代,比如你可以使用下面的命令来指定容器只监听Apache端口:
# docker run --security-opt=label:type:svirt_apache_t -i -t centos bash
注意:此时,你的主机环境中必须存在一个名为svirt_apache_t的安全策略。
Runtime constraints on CPU and memory
下面的参数可以用来调整容器内的性能。
-m="" : Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
-c=0 : CPU shares (relative weight)
通过docker run -m可以调整容器所使用的内存资源。
如果主机支持swap内存,那么使用-m可以设定比主机物理内存还大的值。
同样,通过-c可以调整容器的CPU优先级。
默认情况下,所有的容器拥有相同的CPU优先级和CPU调度周期,但你可以通过Docker来通知内核给予某个或某几个容器更多的CPU计算周期。
比如,我们使用-c或者--cpu-shares =0启动了C0、C1、C2三个容器,使用-c=512启动了C3容器。
这时,C0、C1、C2可以100%的使用CPU资源(1024),但C3只能使用50%的CPU资源(512)
如果这个主机的操作系统是时序调度类型的,每个CPU时间片是100微秒,那么C0、C1、 C2将完全使用掉这100微秒,而C3只能使用50微秒。
Runtime privilege, Linux capabilities, and LXC configuration
--cap-add : Add Linux capabilities
--cap-drop : Drop Linux capabilities
--privileged=false : Give extended privileges to this container
--device=[] : Allows you to run devices inside the container without the --privileged flag.
--lxc-conf=[] : (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
默认情况下,Docker的容器是没有特权的,例如不能在容器中再启动一个容器。这是因为默认情况下容器是不能访问任何其它设备的。但是通过"privileged",容器就拥有了访问任何其它设备的权限。
当操作者执行docker run --privileged时,Docker将拥有访问主机所有设备的权限,同时Docker也会在apparmor或者selinux做一些设置,使容器可以容易的访问那些运行在容器外部的设备。你可以访问Docker博客来获取更多关于--privileged的用法。
同时,你也可以限制容器只能访问一些指定的设备。下面的命令将允许容器只访问一些特定设备:
sudo docker run --device=/dev/snd:/dev/snd ...
默认情况下,容器拥有对设备的读、写、创建设备文件的权限。使用:rwm来配合--device,你可以控制这些权限。
# docker run --device=/dev/sda:/dev/xvdc --rm -it ubuntu fdisk /dev/xvdc
Command (m for help): q
# docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk /dev/xvdc
You will not be able to write the partition table.
Command (m for help): q
# docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk /dev/xvdc
crash....
# docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted
使用--cap-add和--cap-drop,配合--privileged,你可以更细致的控制人哦怒气。
默认使用这两个参数的情况下,容器拥有一系列的内核修改权限,这两个参数都支持all值,如果你想让某个容器拥有除了MKNOD之外的所有内核权限,那么可以执行下面的命令:
# docker run --cap-add=ALL --cap-drop=MKNOD ...
如果需要修改网络接口数据,那么就建议使用--cap-add=NET_ADMIN,而不是使用--privileged。
# run -t -i --rm ubuntu:14.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
# run -t -i --rm --cap-add=NET_ADMIN ubuntu:14.04 ip link add dummy0 type dummy
如果要挂载一个FUSE文件系统,那么就需要--cap-add和--device了。
如果Docker守护进程在启动时选择了lxclxc-driver(docker -d --exec-driver=lxc),那么就可以使用--lxc-conf来设定LXC参数。
但需要注意的是,未来主机上的Docker deamon有可能不会使用LXC,所以这些参数有可能会包含一些没有实现的配置功能。
这意味着,用户在操作这些参数时必须要十分熟悉LXC。
特别注意:当你使用--lxc-conf修改容器参数后,Docker deamon将不再管理这些参数,那么用户必须自行进行管理。
比如说,你使用--lxc-conf修改了容器的IP地址,那么在/etc/hosts里面是不会自动体现的,需要你自行维护。
把当前用户加入到docker用户组中
usermod -a -G docker $USER
===============================
# docker commit -h
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes ##从一个容器的改变创建一个新的镜像
-a, --author= Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change=[] Apply Dockerfile instruction to the created image
--help=false Print usage
-m, --message= Commit message
-p, --pause=true Pause container during commit
============================
# docker tag -h
Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
Tag an image into a repository ##给镜像打标签入库
-f, --force=false Force
--help=false Print usage
给容器打标签
docker tag 11662b14f5e0 ubuntu:jdk1.7
以用户grid_hd登录容器
# docker run -it -u grid_hd ubuntu:hd-salve1
给目录下的所有子目录增加执行权限的脚本
#!/bin/bash
find /mnt/sda4/docker/aufs -type d | while read dir
do
chmod +rx "$dir"
done
启动一个docker容器在后台运行
docker run -d IMAGE[:TAG] 命令
docker logs container_id ##打印该容器的输出
[root@localhost ~]# docker run -d --name mytest docker.io/centos /bin/sh -c "while true; do echo hello world; sleep 2; done"
37738fe3d6f9ef26152cb25018df9528a89e7a07355493020e72f147a291cd17
[root@localhost ~]# docker logs mytest
hello world
hello world
hello world
hello world
docker attach container_id ##附加该容器的标准输出到当前命令行
[root@localhost ~]# docker attach mytest
hello world
hello world
hello world
.......
此时,Ctrl+C退出container(容器消失),按ctrl-p ctrl-q可以退出到宿主机,而保持container仍然在运行
---------------------------------------------------------------
另外,观察以下几点:
commit container只会pause住容器,这是为了保证容器文件系统的一致性,但不会stop。如果你要对这个容器继续做其他修改:
你可以重新提交得到新image2,删除次新的image1
也可以关闭容器用新image1启动,继续修改,提交image2后删除image1
当然这样会很痛苦,所以一般是采用Dockerfile来build得到最终image,参考[]
虽然产生了一个新的image,并且你可以看到大小有100MB,但从commit过程很快就可以知道实际上它并没有独立占用100MB的硬盘空间,而只是在旧镜像的基础上修改,它们共享大部分公共的"片"。
有四种不同的选项会影响容器守护进程的服务名称:
1)-h HOSTNAME 或者 --hostname=HOSTNAME --设置容器的主机名,仅本机可见。
这种方式是写到/etc/hostname ,以及/etc/hosts 文件中,作为容器主机IP的别名,并且将显示在容器的bash中。
不过这种方式设置的主机名将不容易被容器之外可见。这将不会出现在 docker ps 或者 其他的容器的/etc/hosts 文件中。
2)--link=CONTAINER_NAME:ALIAS --使用这个选项去run一个容器, 将在此容器的/etc/hosts文件中增加一个主机名ALIAS,这个主机名是名为CONTAINER_NAME 的容器的IP地址的别名。
这使得新容器的内部进程可以访问主机名为ALIAS的容器而不用知道它的IP。
--link= 关于这个选项的详细讨论请看: Communication between containers.
3)--dns=IP_ADDRESS --设置DNS服务器的IP地址,写入到容器的/etc/resolv.conf文件中。当容器中的进程尝试访问不在/etc/hosts文件中的主机A 时,容器将以53端口连接到IP_ADDRESS这个DNS服务器去搜寻主机A的IP地址。
4)--dns-search=DOMAIN --设置DNS服务器的搜索域,以防容器尝试访问不完整的主机名时从中检索相应的IP。这是写入到容器的 /etc/resolv.conf文件中的。当容器尝试访问主机 host,而DNS搜索域被设置为 example.com ,那么DNS将不仅去查寻host主机的IP,还去查询host.example.com的 IP。
在docker中,如果启动容器时缺少以上最后两种选项设置时,将使得容器的/etc/resolv.conf文件看起来和宿主主机的/etc/resolv.conf文件一致。这些选项将修改默认的设置。
注意一点:当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
1)检查本地是否存在指定的镜像,不存在就从公有仓库下载
2)利用镜像创建并启动一个容器
3)分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
4)从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
5)从地址池配置一个 ip 地址给容器
6)执行用户指定的应用程序
7)执行完毕后容器被终止
简单补充下.......
在ubuntu中安装docker
# sudo apt-get install docker.io
查看docker的版本信息
# docker version
查看安装docker的信息
# docker info
查看本机Docker中存在哪些镜像
# docker images
-------------------------------------------------------
docker pull 拉取镜像
docker push 推送指定镜像
示例:
下载官方 ubuntu docker 镜像,默认下载所有 ubuntu 官方库镜像
[root@localhost ~]# docker pull ubuntu
下载指定版本 ubuntu 官方镜像
[root@localhost ~]# docker pull ubuntu:14.04
推送镜像库到私有源(可注册 docker 官方账户,推送到官方自有账户)
[root@localhost ~]# docker push 192.168.0.100:5000/ubuntu
推送指定镜像到私有源
[root@localhost ~]# docker push 192.168.0.100:5000/ubuntu:14.04
------------------------------------------------------
从 Docker Hub 搜索镜像
# docker search ubuntu:14.04
示例:
查找star数至少为10的ubuntu镜像(默认是不加-s选项)
[root@localhost ~]# docker search -s 10 ubuntu
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/ubuntu Ubuntu is a Debian-based Linux operating s... 5682 [OK]
docker.io docker.io/rastasheep/ubuntu-sshd Dockerized SSH service, built on top of of... 75 [OK]
docker.io docker.io/ubuntu-upstart Upstart is an event-based replacement for ... 70 [OK]
docker.io docker.io/consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC sessi... 45 [OK]
docker.io docker.io/ubuntu-debootstrap debootstrap --variant=minbase --components... 28 [OK]
docker.io docker.io/torusware/speedus-ubuntu Always updated official Ubuntu docker imag... 27 [OK]
docker.io docker.io/nickistre/ubuntu-lamp LAMP server on Ubuntu 16 [OK]
docker.io docker.io/nuagebec/ubuntu Simple always updated Ubuntu docker images... 16 [OK]
-------------------------------------------------------
显示一个镜像的历史
# docker history birdben/ubuntu:v1
列出一个容器里面被改变的文件或者目
# docker diff birdben/ubuntu:v1
从一个容器中取日志
# docker logs birdben/ubuntu:v1
显示一个运行的容器里面的进程信息
# docker top birdben/ubuntu:v1
从容器里面拷贝文件/目录到本地一个路径
# docker cp ID:/container_path to_path
--------------------------------------------------------------------------------------------
查看容器的root用户密码
# docker logs <容器名orID> 2>&1 | grep '^User: ' | tail -n1
因为Docker容器启动时的root用户的密码是随机分配的。所以,通过这种方式就可以得到redmine容器的root用户的密码了。
查看容器日志
# docker logs -f <容器名orID>
-----------------------------------------------------------------------------------
运行一个新容器,同时为它命名、端口映射、文件夹映射。以redmine镜像为例
# docker run --name redmine -p 9003:80 -p 9023:22 -d -v /var/redmine/files:/redmine/files -v /var/redmine/mysql:/var/lib/mysql sameersbn/redmine
一个容器连接到另一个容器
# docker run -i -t --name sonar -d -link mmysql:db tpires/sonar-server sonar
容器连接到mmysql容器,并将mmysql容器重命名为db。这样,sonar容器就可以使用db的相关的环境变量了。
检查某一特定容器可以使用docker inspect命令,后面跟容器的名称或唯一ID。
Docker自动创建的容器名称同样是不方便记忆的,所以最好在运行容器时使用--name参数为其指定一个名称,命令格式为docker run --name=<yourname>。
# docker inspect App_Container
使用logs命令查看守护式容器
可以通过使用docker logs命令来查看容器的运行日志,其中--tail选项可以指定查看最后几条日志,而-t选项则可以对日志条目附加时间戳。使用-f选项可以跟踪日志的输出,直到手动停止。
docker logs [OPTIONS] CONTAINER
# docker logs App_Container
查看运行中容器内的进程
docker top CONTAINER [ps OPTIONS]
# docker top App_Container
构建自己的镜像
# docker build -t <镜像名> <Dockerfile路径>
如Dockerfile在当前路径:
# docker build -t xx/gitlab .
重新查看container的stdout
# 启动top命令,后台运行
$ ID=$(sudo docker run -d ubuntu /usr/bin/top -b)
# 获取正在running的container的输出
$ sudo docker attach $ID
top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355560k used, 18012k free, 27872k buffers
Swap: 786428k total, 0k used, 786428k free, 221740k cached
^C$
$ sudo docker stop $ID
后台运行(-d)、并暴露端口(-p)
# docker run -d -p 127.0.0.1:33301:22 centos6-ssh
从Container中拷贝文件出来
# sudo docker cp 7bb0e258aefe:/etc/debian_version .
拷贝7bb0e258aefe中的/etc/debian_version到当前目录下。
注意:只要7bb0e258aefe没有被删除,文件命名空间就还在,可以放心的把exit状态的container的文件拷贝出来
列出当前所有正在运行的容器
# docker ps
# docker ps -a 为查看所有的容器,包括已经停止的。
# docker ps -q 查找已运行的docker容器的ID
# docker ps -a -q 查找所有的docker容器的ID
# docker ps -l 列出最近一次启动的容器
查看容器的相关信息 # docker inspect CONTAINER_ID
显示容器IP地址和端口号,如果输出是空的说明没有配置IP地址(不同的Docker容器可以通过此IP地址互相访问) # docker inspect --format='{{.NetworkSettings.IPAddress}}' CONTAINER_ID
保存对容器的修改 # docker commit -m "Added ssh from ubuntu14.04" -a "birdben" 6s56d43f627f3 birdben/ubuntu:v1 参数: -m参数用来来指定提交的说明信息; -a可以指定用户信息的; 6s56d43f627f3代表的时容器的id; birdben/ubuntu:v1指定目标镜像的用户名、仓库名和 tag 信息。
构建一个容器 # docker build -t="birdben/ubuntu:v1" . 参数: -t为构建的镜像制定一个标签,便于记忆/索引等 . 指定Dockerfile文件在当前目录下,也可以替换为一个具体的 Dockerfile 的路径。
在docker中运行ubuntu镜像 # docker run <相关参数> <镜像 ID> <初始命令>
守护模式启动 # docker run -it ubuntu:14.04
交互模式启动 # docker run -it ubuntu:14.04 /bin/bash
指定端口号启动 # docker run -p 80:80 birdben/ubuntu:v1
指定配置启动 # sudo docker run -d -p 10.211.55.4:9999:22 birdben/ubuntu:v1 '/usr/sbin/sshd' -D
参数: -d:表示以“守护模式”执行,日志不会出现在输出终端上。 -i:表示以“交互模式”运行容器,-i 则让容器的标准输入保持打开 -t:表示容器启动后会进入其命令行,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上 -v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>,-v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。 -p:表示宿主机与容器的端口映射,此时将容器内部的 22 端口映射为宿主机的 9999 端口,这样就向外界暴露了 9999 端口,可通过 Docker 网桥来访问容器内部的 22 端口了。 注意: 这里使用的是宿主机的 IP 地址:10.211.55.4,与对外暴露的端口号 9999,它映射容器内部的端口号 22。ssh外部需要访问:ssh root@10.211.55.4 -p 9999 不一定要使用“镜像 ID”,也可以使用“仓库名:标签名”
根据镜像启动容器的时候,如果镜像的TAG是latest,那么就直接跟镜像名就行了;如果TAG不是latest,那么镜像后面要跟上这个TAG标识。如下:
[root@linux-node2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 0ef2e08ed3fa 2 weeks ago 130 MB
centos7 7.3.1611 d5ebea14da54 3 weeks ago 311 MB
由于ubuntu镜像的TAG标识是latest,那么容器启动的时候,镜像后面的TAG信息可以省略。
[root@linux-node2 ~]# docker run -i -t ubuntu /bin/bash
但是centos7镜像的TAG标识不是latest,所以容器启动的时候必须要跟上这个TAG信息。
[root@linux-node2 ~]# docker run -i -t centos7:7.3.1611 /bin/bash
[root@2ba57568e836 /]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
不跟TAG的话,就会报错
[root@linux-node2 ~]# docker run -i -t centos7 /bin/bash
Unable to find image 'centos7:latest' locally
Pulling repository docker.io/library/centos7
docker: Error: image library/centos7:latest not found.
See 'docker run --help'.
docker运行一个容器必须是基于镜像来进行的,一旦容器启动了,我们就可以登录到容器中,安装自己所需的软件或应用程序。 启动容器的命令中必须跟一个镜像,启动容器后执行的命令必须放在镜像后面,如下,/bin/bash必须放在镜像名称的后面:
[root@linux-node2 ~]# docker run -i -t daocloud.io/library/ubuntu /bin/bash
root@a7b997da8ba3:/# cat /etc/issue
Ubuntu 16.04.1 LTS \n \l
root@a7b997da8ba3:/# [root@linux-node2 ~]# docker run -i -t ubuntu /bin/bash
root@d96c6b85cace:/# cat /etc/issue
Ubuntu 16.04.1 LTS \n \l
root@d96c6b85cace:/#
[root@linux-node2 ~]# docker run -t -i -v /home/wangshibo/docker:/home/mycontainer:rw -p 8888:8080 centos /bin/bash
[root@8f65f826ad80 /]#
[root@linux-node2 ~]# docker run -i -t centos7:7.3.1611 /bin/bash
[root@4941394a1e92 /]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@linux-node2 ~]# docker run -i -t centos:centos6 /bin/bash
[root@357eaa658c87 /]# cat /etc/redhat-release
CentOS release 6.8 (Final)
注意:创建应用容器的时候,一般会做端口映射,这样是为了让外部能够访问这些容器里的应用。可以通过-P或-p参数来指定端口映射
1)当使用-p标记时,可以指定端口映射,即容器端口映射到宿主机的对应端口。可以用多个-p指定多个端口映射关系。如下:
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/redis latest e4a35914679d 2 weeks ago 182.9 MB
[root@localhost ~]# docker run --name myredis -p 63799:6379 -d docker.io/redis
f5d5ff51ace01c5f26fcd65a6ca4853f8556a333c812576123ed71fd3d405737
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5d5ff51ace0 docker.io/redis "docker-entrypoint.sh" 6 seconds ago Up 5 seconds 0.0.0.0:63799->6379/tcp myredis
[root@localhost ~]# docker run --rm -it --name myredis2 --link myredis:redisdb docker.io/redis /bin/bash
root@16b660ff9f65:/data# redis-cli -h redisdb -p 6379
redisdb:6379> ping
PONG
redisdb:6379> set test linux
OK
redisdb:6379>
在别的机器上通过访问本机的63799端口连接这个容器的redis
[root@linux-node2 ~]# redis-cli -h 192.168.1.23 -p 63799
192.168.1.23:63799> get test
"linux"
192.168.1.23:63799>
------------------------------------------------------------------------------------------
可以使用多个-p映射多个端口
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7 7.3.1611 d5ebea14da54 3 weeks ago 311 MB
[root@localhost ~]# docker run -i -t -p 20022:22 -p 8088:80 centos7:7.3.1611 /bin/bash
[root@1a7a949e2f41 /]#
------------------------------------------------------------------------------------------
2)当使用-P标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。如下:
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/redis latest e4a35914679d 2 weeks ago 182.9 MB
[root@localhost ~]# docker run --name myredis -P -d docker.io/redis
805d0e21e531885aad61d3e82395210b50621f1991ec4b7f9a0e25c815cc0272
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
805d0e21e531 docker.io/redis "docker-entrypoint.sh" 4 seconds ago Up 3 seconds 0.0.0.0:32768->6379/tcp myredis
从上面的结果中可以看出,本地主机的32768端口被映射到了redis容器的6379端口上,也就是说访问本机的32768端口即可访问容器内redis端口。
测试看下,登陆redis容器,随意写个数据
[root@localhost ~]# docker run --rm -it --name myredis2 --link myredis:redisdb docker.io/redis /bin/bash
root@be44d955d6f4:/data# redis-cli -h redisdb -p 6379
redisdb:6379> set wangshibo huanqiu
OK
redisdb:6379>
在别的机器上通过上面映射的端口32768连接这个容器的redis
[root@linux-node2 ~]# redis-cli -h 192.168.1.23 -p 32768
192.168.1.23:32768> get wangshibo
"huanqiu"
start 启动容器(多个容器,后面就跟多个容器id) # docker start 117843ade696117843ade696
stop 停止正在运行的容器(多个容器,后面就跟多个容器id)(在容器里面按ctrl+d组合键,也会退出当前容器) # docker stop 117843ade696117843ade696
restart 重启容器(多个容器,后面就跟多个容器id) # docker restart 117843ade696117843ade696
删除容器和镜像
rm 删除容器(删除一个或多个,多个之间用空格隔开)
# docker rm 117843ade696117843ade696
杀死所有running状态的容器
# docker kill $(docker ps -a -q)
# docker rm $(docker ps -a -q)
-----------------------------------------------------------------------------------
rmi 删除镜像(删除一个或多个,多个之间用空格隔开)
# docker rmi ed9c93747fe1Deleted
删除所有未打tag的镜像
# docker rmi $(docker images -q | awk '/^<none>/ { print $3 }')
删除所有镜像
# docker rmi $(docker images -q)
根据格式删除所有镜像
# docker rm $(docker ps -qf status=exited)
登录Docker Hub中心 # docker login
发布上传image(push) # docker push birdben/ubuntu:v1
Docker本机和容器之间的文件拷贝:
1)将本机的/root/test.file文件传输到ID为7bb0e258aefe的容器里的/mnt/wang目录下
# docker cp /root/test.file 7bb0e258aefe:/mnt/wang/
2)拷贝ID为7bb0e258aefe的容器里的/var/id.list文件到本机的/opt下
# docker cp 7bb0e258aefe:/var/id.list /opt/
实例如下:
[root@linux-node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7bd050b0a23 centos "/bin/bash" 2 hours ago Up 2 hours small_almeida
eaf66f1e43ab centos "/sbin/init" 7 weeks ago Up 7 weeks 0.0.0.0:8888->8080/tcp hungry_khorana
[root@linux-node2 ~]# docker exec -it eaf66f1e43ab /bin/bash
[root@eaf66f1e43ab /]# cd /mnt/
[root@eaf66f1e43ab mnt]# ls
[root@eaf66f1e43ab mnt]# mkdir test-haha
[root@eaf66f1e43ab mnt]# cd test-haha
[root@eaf66f1e43ab test-haha]# touch a b c
[root@eaf66f1e43ab test-haha]# pwd
/mnt/test-haha
[root@eaf66f1e43ab test-haha]# ls
a b c
[root@eaf66f1e43ab test-haha]#
然后拷贝容器文件出来
[root@linux-node2 ~]# docker cp eaf66f1e43ab:/mnt/test-haha /opt/
[root@linux-node2 ~]# ls /opt/test-haha/
a b c
镜像的存出和载入(可以将本机下载的镜像导出,然后将导出文件上传到别的机器上,在别的机器上进行镜像导入)
1)如果要导出镜像到本地文件,可以使用 docker save命令。
拉取镜像
[root@linux-node2 ~]# docker pull ubuntu:14.04
[root@linux-node2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 c4ff7513909d 5 weeks ago 225.4 MB
导出镜像
[root@linux-node2 ~]# docker save ubuntu:14.04 > /opt/ubuntu_14.04.tar.gz
或者:
[root@linux-node2 ~]# docker save -o /opt/ubuntu_14.04.tar.gz ubuntu:14.04
2)将上面的镜像导出文件上传到linux-node1机器上,然后在linux-node1机器上使用docker load命令载入这个镜像
[root@linux-node1 ~]# docker load < /opt/ubuntu_14.04.tar.gz
或者:
[root@linux-node1 ~]# docker load --input ubuntu_14.04.tar
实例如下:
[root@linux-node2 opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7 7.3.1611 1d7e06aab5db 24 hours ago 264.7 MB
nginx 1.9 c8c29d842c09 9 months ago 182.7 MB
[root@linux-node2 opt]# docker save nginx:1.9 > /opt/nginx:1.9.tar.gz
[root@linux-node2 opt]# ls
nginx:1.9.tar.gz
[root@linux-node2 opt]# rsync -e "ssh -p22" -avpgolr /opt/nginx:1.9.tar.gz 192.168.1.23:/opt/
登陆192.168.1.23
[root@localhost ~]# cd /opt/
[root@localhost opt]# ls
nginx:1.9.tar.gz
[root@localhost opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 980e0e4c79ec 5 months ago 196.7 MB
docker.io/redis 2.8.19 dd9fe7db5236 22 months ago 110.7 MB
导入nginx镜像
[root@localhost opt]# docker load < /opt/nginx:1.9.tar.gz
[root@localhost opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 980e0e4c79ec 5 months ago 196.7 MB
nginx 1.9 c8c29d842c09 9 months ago 182.7 MB
docker.io/redis 2.8.19 dd9fe7db5236 22 months ago 110.7 MB
容器的导出和导入(可以依据导出的容器快照导入为镜像,在本地或将容器快照文件上传到别的机器上进行导入镜像操作都可以)
1)导出容器
如果要导出本地某个容器,可以使用 docker export 命令。
[root@linux-node2 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5243af7921c5 centos "/bin/bash" 2 days ago Exited (0) 5 seconds ago sharp_saha
[root@linux-node2 ~]# docker export 5243af7921c5 > /opt/centos.tar.gz
[root@linux-node2 ~]# ls /opt/
centos.tar.gz
这样将导出上面的ID为5243af7921c5的容器快照到本地的/opt/centos.tar.gz文件了。
2)导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像
为了测试效果,先删除ID为5243af7921c5的容器,再导入
[root@linux-node2 ~]# docker rm 5243af7921c5
5243af7921c5
[root@linux-node2 ~]# cat /opt/centos.tar.gz | docker import - test/centos:v1.0
sha256:d84d758c5cda4aced7cd24a4efefedb3d56076ae127133dac8ac79ca0bab3f3d
或者使用下面命令导入
[root@linux-node2 ~]# docker import /opt/centos.tar.gz test/centos:v1.0
[root@linux-node2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/centos v1.0 d84d758c5cda 5 seconds ago 191.8 MB
[root@linux-node2 ~]# docker run -t -i test/centos:v1.0 /bin/bash
[root@5056db543cc2 /]#
[root@linux-node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5056db543cc2 test/centos:v1.0 "/bin/bash" 19 seconds ago Up 18 seconds tiny_dijkstra
这个ID为5056db543cc2的新容器既是导入的上面的容器快照创建的
温馨提示:
用户既可以使用docker load来导入镜像存储文件到本地镜像库,也可以使用docker import 来导入一个容器快照到本地镜像库。
这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。
此外,从容器快照文件导入时可以重新指定标签等元数据信息。
比如说我在A机器上有个nginx容器,现在要在B机器上启动一个一模一样的nginx容器(或者说将A机器上的nginx容器拿到B机器上),方法有下面两种:
1)将A机器上将nginx容器提交为新的镜像(docker commit),然后将这个镜像导出并上传到B机器上,最后在B机器上导入这个新镜像并依据这个镜像启动容器,这个就和A机器上的nginx容器一样了。
2)将A机器上的nginx容器做快照,然后从这个快照文件中导入为镜像,将这个镜像上传到B机器上,最后在B机器上导入这个新镜像并依据它启动容器。
在运行状态中的容器内再次启动新的进程(docker exec)
虽然Docker鼓励我们一个容器只运行一个服务,但是当我们需要对运行中的容器进行监控、维护和管理时,通常需要为运行中的容器启动新进程。
# docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
这条命令与docker run极为相似,也可以使用-i、-t和-d等参数。
[root@linux-node2 ~]# docker exec -i -t App_Container /bin/bash
示例如下:
创建一个tomcat容器(创建容器后,启动容器的/bin/bash进程)
[root@localhost ~]# docker run -t -i -d --name=tomcat --hostname=wangshibo --dns=8.8.8.8 -p 8888:8080 tomcat7 /bin/bash
a5ab82945a88d16c51941c7fbc1e3f581823099835f96423c4fd19b44841b31c
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a5ab82945a88 tomcat7 "/bin/bash" 3 seconds ago Up 2 seconds 0.0.0.0:8888->8080/tcp tomcat
在上面tomcat容器已经启动的状态下,再在宿主机上启动该容器中新的进程。(当然也可以直接登陆容器内启动这个进程)
[root@localhost ~]# docker exec tomcat /usr/local/tomcat7/bin/startup.sh //如果启动后出现卡的情况,就ctrl+c,不影响启动结果。
Tomcat started.
登陆到该容器内验证,发现tomcat进程已经通过上面的docker exec启动了
[root@localhost ~]# docker start tomcat
tomcat
[root@localhost ~]# docker attach tomcat
[root@wangshibo /]# ps -ef|grep tomcat
root 40 1 19 09:17 ? 00:00:08 java -Djava.util.logging.config.file=/usr/local/tomcat7/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat7/endorsed -classpath /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat7 -Dcatalina.home=/usr/local/tomcat7 -Djava.io.tmpdir=/usr/local/tomcat7/temp org.apache.catalina.startup.Bootstrap start
root 77 1 0 09:17 ? 00:00:00 grep --color=auto tomcat
----------------------------------------------------------------------------------------------------------- 一般来说,容器创建后的主机名都是随机生成的一串字符。DNS也是默认和宿主机一样的(/etc/resolv.conf) 容器创建后,登陆容器是无法修改主机名或DNS配置的,会报错说:需要root权限才能修改! 其实容器的主机名或DNS配置是可以在容器创建的时候手动指定的:
1)创建容器时使用"-h HOSTNAME" 或者 "--hostname=HOSTNAME"参数就可以指定容器的主机名。
设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。但它在容器外部看不到,既不会在 docker ps 中显示,也不会在其他的容器的 /etc/hosts 看到。
2)创建容器时使用"--dns=IP_ADDRESS"参数就可以指定容器的DNS
添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
3)创建容器时使用"--link=CONTAINER_NAME:ALIAS"参数
选项会在创建容器的时候,添加一个其他容器的主机名到 /etc/hosts 文件中,让新容器的进程可以使用主机名 ALIAS 就可以连接它。
实例:
手动设置主机名和DNS
[root@localhost ~]# docker run -t -i -d --name=tomcat --hostname=wangshibo --dns=8.8.8.8 -p 8888:8080 tomcat7 /bin/bash
4ccc7415aab8645fa2f76cac5b484c5e7195bec4da355069df4e7df62bd53e2f
[root@localhost ~]# docker attach tomcat
[root@wangshibo /]# cat /etc/hostname
wangshibo
[root@wangshibo /]# 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 wangshibo
[root@wangshibo /]# cat /etc/resolv.conf
search localdomain
nameserver 8.8.8.8
[root@wangshibo /]# ping www.baidu.com
PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=51 time=36.0 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=51 time=35.9 ms
......
[root@wangshibo /]# /usr/local/tomcat7/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat7
Using CATALINA_HOME: /usr/local/tomcat7
Using CATALINA_TMPDIR: /usr/local/tomcat7/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar
Tomcat started.
[root@wangshibo /]# yum install -y lsof
[root@wangshibo /]# yum install -y net-tools
[root@wangshibo /]# lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 35 root 44u IPv6 30851404 0t0 TCP *:webcache (LISTEN)
[root@wangshibo /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:2 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 149 bytes 660403 (644.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 108 bytes 7655 (7.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
做容器链接
[root@localhost ~]# docker run -t -i -d --name=my_tomcat --link tomcat:hahaha tomcat7 /bin/bash
996e16302d460c725f3685f98935fa3b61335ac19ccf2c4daf8615b492b1ac56
[root@localhost ~]# docker attach my_tomcat
[root@996e16302d46 /]# 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 hahaha wangshibo
172.17.0.3 996e16302d46
[root@996e16302d46 /]# yum install -y net-tools
[root@996e16302d46 /]# yum install -y telnet
[root@996e16302d46 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 86 bytes 382330 (373.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 74 bytes 5338 (5.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
在本容器链接tomcat容器的8080端口,则可以使用别名hahaha
[root@996e16302d46 /]# ping hahaha
PING hahaha (172.17.0.2) 56(84) bytes of data.
64 bytes from hahaha (172.17.0.2): icmp_seq=1 ttl=64 time=0.170 ms
64 bytes from hahaha (172.17.0.2): icmp_seq=2 ttl=64 time=0.053 ms
[root@996e16302d46 /]# telnet hahaha 8080
Trying 172.17.0.2...
Connected to hahaha.
Escape character is '^]'.
Docker容器登陆的方法: 具体参考:Docker容器学习梳理--容器登陆方法梳理(attach、exec、nsenter)
查看docker中对应容器的IP
命令格式:docker inspect 容器ID |grep IPAddress
比如查看ID为b220fabf815a的容器的ip
[root@localhost ~]# docker inspect b220fabf815a|grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAddress": "172.17.0.4",
或者使用“yum install net-tools”,安装后就可以使用ifconfig命令查看ip了
docker inspect 命令:显示更底层的容器或image信息(docker inspect images_id/container_id 查看镜像或容器信息)
Usage: docker inspect CONTAINER|IMAGE [CONTAINER|IMAGE...]Return low-level information on a container or image -f,--format=""Format the output using the given go template.
默认返回一个json字符串,更具结构自行提取信息即可
docker inspect命令用于获取容器/镜像的元数据,其中-f参数可以用于获取指定的数据。不过很多用户容易被该特性的语法搞晕,并很少有人能将它的优势发挥出来(大部分人都是通过 grep 来获取指定数据,虽然有效但比较零散混乱)。本文将详细介绍 -f 参数,并给出一些例子来说明如何使用它。
下面是针对ID为b220fabf815a的容器的相关inspect命令
[root@localhost ~]# docker inspect b220fabf815a
显示实例ip:
# docker inspect --format='{{.NetworkSettings.IPAddress}}' $INSTANCE_ID
[root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' b220fabf815a
172.17.0.4
也可以通过grep来获取ip
[root@localhost ~]# docker inspect b220fabf815a|grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAddress": "172.17.0.4",
或者使用“yum install net-tools”,安装后就可以使用ifconfig命令查看ip了
列出所有绑定的端口:
# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' $INSTANCE_ID
[root@localhost ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' b220fabf815a
22/tcp -> 20020
找出特殊的端口映射:
比如找出容器里22端口所映射的docker本机的端口:
# docker inspect --format='{{(index (index .NetworkSettings.Ports "22/tcp") 0).HostPort}}' $INSTANCE_ID
[root@localhost ~]# docker inspect --format='{{(index (index .NetworkSettings.Ports "22/tcp") 0).HostPort}}' b220fabf815a
20020
特别注意一个细节:
1)ubuntu14下的docker是没有service服务。去除每次sudo运行docker命令,需要添加组:
# Add the docker group if it doesn't already exist.
$ sudo groupadd docker
#改完后需要重新登陆用户
$ sudo gpasswd -a ${USER} docker
2)ubuntu14的febootstrap没有-i命令
3)Dockerfile中的EXPOSE、docker run --expose、docker run -p之间的区别
Dockerfile的EXPOSE相当于docker run --expose,提供container之间的端口访问。docker run -p允许container外部主机访问container的端口
---------------------------------------------------无法删除状态为Dead的容器--------------------------------------------------- docker中有两个status为dead的容器,删除时报错如下: Error response from daemon: Driver devicemapper failed to remove root filesystem 33ddd2513fc3cb732fa02e912be1927929d8d028abefa945d8a3984d700a4d74: Device is Busy
解决办法: 1)看容器进程是否已经杀掉。没有的话,可以手动杀死。 2)mount -l看是不是该容器的路径还在挂载状态。是的话,umount掉。 3)然后再次尝试docker rm container_id 尽量不要手动去移除dm和docker里面container的相关文件,以免造成垃圾数据。 4)尝试docker rm -f <container-id>,强制删除 这样可以删除掉docker daemon中的container信息(但是已经创建的dm还是ACTIVE的,所以还要再去把dm给删除了)
[root@linux-node2 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7bd050b0a23 centos "/bin/bash" About an hour ago Up About an hour small_almeida
33ddd2513fc3 centos "/bin/bash" 7 weeks ago Dead App_Container
eaf66f1e43ab centos "/sbin/init" 7 weeks ago Up 7 weeks 0.0.0.0:8888->8080/tcp hungry_khorana
[root@linux-node2 ~]# docker rm -f 33ddd2513fc3
Error response from daemon: Driver devicemapper failed to remove root filesystem 33ddd2513fc3cb732fa02e912be1927929d8d028abefa945d8a3984d700a4d74: Device is Busy
加上-f参数后,虽然删除时还是报错,然是container信息已经删除了
[root@linux-node2 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7bd050b0a23 centos "/bin/bash" About an hour ago Up About an hour small_almeida
eaf66f1e43ab centos "/sbin/init" 7 weeks ago Up 7 weeks 0.0.0.0:8888->8080/tcp hungry_khorana
---------------------------------------------------容器启动失败错误1---------------------------------------------------
docker: Error response from daemon: failed to create endpoint mosredis on network bridge: iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.6 -j ACCEPT: iptables: No chain/target/match by that name.
(exit status 1).
解决办法:
一般来说,重启docker服务,即可解决这个问题。
[root@localhost ~]# systemctl restart docker
[root@localhost ~]#
----------------------------------
如果重启docker服务解决不了,那么如下操作:
[root@localhost ~]# pkill docker
[root@localhost ~]# iptables -t nat -F
[root@localhost ~]# ifconfig docker0 down
[root@localhost ~]# brctl delbr docker0
---------------------------------------------------容器启动失败错误2---------------------------------------------------
docker: Error response from daemon: Cannot start container b0a845a3dedeac7b46002d1c8514077309d88dcc0667b7080bc1ab67d70eb167: [9] System error: SELinux policy denies access..
如上出现上面的报错,这是由于selinux造成的!需要关闭selinux,如下:
[root@localhost ~]# setenforce 0
[root@localhost ~]# getenforce
Permissive
---------------------------------------------------容器yum不能使用--------------------------------------------------
容器启动后登陆进去,发现yum不能用,报错如下:
[root@5e91e12186e1 /]# yum list
........
yum-config-manager --disable <repoid>
........
yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true
解决办法:(再不行,就重启下docker服务,然后登陆容器试试)
先保证容器能正常联网(ping www.baidu.com试试)
# yum clean all
# yum makecache
==============关于docker容器和镜像以及文件的几个转化关系==============
容器转成镜像:
# docker commit <CONTAINER ID> imagename01
容器转成文件:
# docker export <CONTAINER ID> > /home/export.tar
镜像转成文件:
# docker save imagename01 > /home/save.tar
注:一般情况下,save.tar比export.tar大一点点而已,export比较小,因为它丢失了历史和数据元metadata
文件转成镜像:
# cat /home/export.tar | docker import - imagename02:latest
save.tar文件转成镜像:
# docker load < /home/save.tar
查看转成的镜像:
# docker images
注意:这里一个镜像经过n次转化之后,可以用sudo docker images --tree查看历史,用docker tag <LAYER ID> <IMAGE NAME>可以回到某个层(只针对save命令可以回到某个层!)
-------------------------------------基于centos7的docker容器出现的一个bug--------------------------------------
centos7下部署的docker容器中启动服务,报错如下:
[root@a3c8baf6961e .ssh]# systemctl restart sshd.service
Failed to get D-Bus connection: Operation not permitted
这是centos7容器里面出现的一个BUG!
即centos7镜像创建的容器里面安装服务后,不能用systemctl/service启动服务,centos6的容器里没有这个坑!
可以通过使用其他的方式启动或者换用centos6的镜像来避免这个错误。
解决方案如下:
原因是dbus-daemon没能启动。其实systemctl并不是不可以使用,可以将你的CMD设置为/usr/sbin/init即可。
这样就会自动将dbus等服务启动起来。即采用 /usr/sbin/init自动启动dbus daemon
即把之前的容器关闭并删除(docker stop container-id),然后重新启动容器,注意:
启动时一定要加上参数--privileged和/sbin/init,如下:
[root@localhost ~]# docker run --privileged -i -t centos7:7.3.1611 /sbin/init
上面的容器启动后,会一直在卡着的状态中,先不用管,打开另一个终端窗口,查看容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af40bd07fa0f centos7:7.3.1611 "/sbin/init" 28 seconds ago Up 28 seconds nauseous_shirley
然后按照容器的ID进去,这个时候再根据/bin/bash进入容器(前面加exec -it参数),接着重启ssh服务就ok了
[root@localhost ~]# docker exec -it af40bd07fa0f /bin/bash
[root@af40bd07fa0f /]# systemctl restart sshd.service
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有