docker images
docker rmi 镜像Id(即:1.1图中的IMAGE ID)
有时候删除会失败,比如:有一个容器正在使用该镜像文件。这时可以加参数-f 强制删除,如果不清楚每个命令可以加哪些参数,可以用
docker 命令 --help
bin docker rmi --help
Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]
Remove one or more images
-f, --force=false Force removal of the image
--help=false Print usage
--no-prune=false Do not delete untagged parents
docker run -it ubuntu
参数-it的含义,可以用docker run --help查看,就不展开了
docker run -it ubuntu echo 'hello world'
docker run -it --name 'myubuntu' ubuntu
容器名称是一个很有意思的东东,后面马上会讲到。上面的命令运行完以后,先用exit退出,以便后面学习其它命令。
docker ps -a
可以做一个小试验,刚才我们已经创建了一个名为myubuntu的容器:
docker run -it --name 'myubuntu' ubuntu
Error response from daemon: Conflict. The name "myubuntu" is already in use by container d1c261ad0b1e. You have to remove (or rename) that container to be able to reuse that name.
大意是容器名称mybutun已经被另一个容器(ID为d1c261ad0b1e)占用了,要么把原来的容器删除,要么换个名字。
docker stop 容器名称
docker rm 容器ID
如果容器处于运行状态,上面的操作会失败,可以加-f参数强制删除
docker exec 容器名称 命令
docker exec myubuntu apg-get update
docker attach 容器名称
注:该命令运行后,mac上屏幕没任何输出,还以为卡死了,这是假象,直接继续输入命令,比如pwd之类的就能看到结果了.
docker exec -it 容器名称 sh
当然进入容器还有其它一些办法,比如网络端口22映射本机某个端口,容器里启动ssh服务,然后ssh连接进入,或者用nsenter结合进程id进入,但个人觉得这些方法操作都太复杂,远不如上面这行命令简单
docker commit -a 作者名字 -m 提交原因 -p 容器ID 镜像名称:版本号
docker commit -a 'yjmyzz' -m 'test commit' -p d1c261ad0b1e yjmyzz/ubuntu:V2
docker images 查看
从图中可以看出,在ubuntu原来的基础上,生成一个名为yjmyzz/ubuntu的新镜像,然后用新镜像创建容器试试看
docker run -it --name 'myubuntu2' yjmyzz/ubuntu:V2
docker run -it -v /Users/yjmyzz/docker_volumn:/opt/webapp --name myubuntu ubuntu /bin/bash
可以尝试在host本机修改下/Users/yjmyzz/docker_volumn/index.html这个文件,然后在容器中cat看下内容,应该马上就能看到最新的内容。
权限问题,mac机上如果从网上down(非apple store官方)了一个文件到本机,该文件甚至保存文件的目录权限,都会被设置成特殊权限@,见下面的截图:
这本来是mac 10.5以后做的一项安全改进,有此标识的程序,在首次执行时会提示
但是有这类特殊权限的目录或文件,被挂到容器中后,docker容器内根本看不到,也就是无权读取。处理办法:
ll -l@ -a
然后用xattr -r -d 详细信息 * 去掉这些特殊权限(参考下图),然后再重新挂到容器中,就能正常使用了
mac上挂载的本机目录,必须是在~/(即:当前用户的目录)下,类似/opt/www这样的目录,就算给它所有权限,挂到容器中后,也只能看到目录,读不到任何文件,centOS上没这问题。
docker inspect myubuntu
查看此时容器的所有状态,会看到一段长长的json输出,类似下面这样:
[
{
"Id": "21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48",
"Created": "2016-01-28T02:23:43.91086474Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1843,
"ExitCode": 0,
"Error": "",
"StartedAt": "2016-01-28T02:26:09.414485616Z",
"FinishedAt": "2016-01-28T02:25:43.868883111Z"
},
"Image": "8693db7e8a0084b8aacba184cfc4ff9891924ed2270c6dec6a9d99bdcff0d1aa",
"ResolvConfPath": "/mnt/sda1/var/lib/docker/containers/21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48/resolv.conf",
"HostnamePath": "/mnt/sda1/var/lib/docker/containers/21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48/hostname",
"HostsPath": "/mnt/sda1/var/lib/docker/containers/21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48/hosts",
"LogPath": "/mnt/sda1/var/lib/docker/containers/21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48/21d15713166ae83b022eea8806bd466da9917422e487e874cc098a0f1329dd48-json.log",
"Name": "/myubuntu",
"RestartCount": 0,
"Driver": "aufs",
"ExecDriver": "native-0.2",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": [
"/Users/yjmyzz/docker_volumn:/opt/webapp"
],
"ContainerIDFile": "",
"LxcConf": [],
"Memory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"KernelMemory": 0,
"CpuShares": 0,
"CpuPeriod": 0,
"CpusetCpus": "",
"CpusetMems": "",
"CpuQuota": 0,
"BlkioWeight": 0,
"OomKillDisable": false,
"MemorySwappiness": -1,
"Privileged": false,
"PortBindings": {},
"Links": null,
"PublishAllPorts": false,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"VolumesFrom": null,
"Devices": [],
"NetworkMode": "default",
"IpcMode": "",
"PidMode": "",
"UTSMode": "",
"CapAdd": null,
"CapDrop": null,
"GroupAdd": null,
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"SecurityOpt": null,
"ReadonlyRootfs": false,
"Ulimits": null,
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"CgroupParent": "",
"ConsoleSize": [
0,
0
],
"VolumeDriver": ""
},
"GraphDriver": {
"Name": "aufs",
"Data": null
},
"Mounts": [
{
"Source": "/Users/yjmyzz/docker_volumn",
"Destination": "/opt/webapp",
"Mode": "",
"RW": true
}
],
"Config": {
"Hostname": "21d15713166a",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": null,
"Cmd": [
"/bin/bash"
],
"Image": "ubuntu",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {},
"StopSignal": "SIGTERM"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "893c76e283a75e3eebb474bf1b5bce901a37778de3514b526312134fcc858d2c",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/893c76e283a7",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "a7fee41964177719fbd149df820bf66dbd976ebe7cea0b68497ae2fe4c06efc5",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"EndpointID": "a7fee41964177719fbd149df820bf66dbd976ebe7cea0b68497ae2fe4c06efc5",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
}
}
]
90~97行的Mounts节点描述了当前容器挂载的"卷"信息。
jpetazzo.github.io/2015/01/13/…
docker volume ls
docker volume rm 卷名称
tips:如果要批量删除所有卷,一个一个rm显然太麻烦了,可以用下面的方式快速搞定
docker-machine ssh default
docker volume inspect 卷名
sudo -i
cd /var/lib/docker/volumes/
上图的ls命令已经说明,所谓的数据卷,其实就是一个个目录,再次印证了linux里的一句名言『一切皆是文件』,剩下的事情,地球人都知道了,邪恶的
rm -rf *
docker-machine restart default
如果多个容器之间希望共享一份数据,除了上面的方式外,docker还允许定义一个专用的容器,这个容器啥也不干,只用来放数据,这种容器称为『数据卷容器』
docker run -it -v /Users/yjmyzz/docker_volumn:/sites --name site_files kitematic/hello-world-nginx echo 'only for nginx web files'
docker run -d --volumes-from site_files --name nginx1 kitematic/hello-world-nginx sh ./start.sh
注意上面的--volumes-from site_files 这个就是使用数据卷容器的关键,其它跟之前的完全相同,多个容器可以挂同一个数据卷容器,一个容器也可以挂多个数据卷容器。
-p IP:host_port:container_port
上面的参数表示将本机IP上的hostport映射到容器的container_port,示例:
docker run -it -v /Users/yjmyzz/Documents/Kitematic/hello-world-nginx/website_files:/website_files -p 0.0.0.0:10080:80 --name my-nginx kitematic/hello-world-nginx sh /start.sh
这个命令更长了,结合了之前所有学习到的参数,注意多出的问题-p 0.0.0.0:10080:80,表示将本机10080端口映射到容器80端口
注:如果把-p换成大写的-P,系统会随机映射到本机一个空闲的端口号
默认创建容器时,hostname是一个唯一的随机字符串,很难记,可以在docker run -h hostname名称来指定,这个就不演示了
假如有二个容器mysql, appserver,通常appserver中要访问数据库,所以需要appserver能直接访问mysql,下面演示了如何实现:
docker run -it -h mysql --name mysql ubuntu /bin/bash
docker run -it -h appserver --name appserver --link mysql:mysqlserver ubuntu /bin/bash
注意其中的--link mysql:mysqlserver,冒号前的为容器名称,冒号后的为容器别名,启动后appserver中就能直接ping通mysql容器了,见下图:








