您的位置:首页 > 运维架构 > Docker

docker使用入门

2014-07-16 11:05 531 查看
这段时间在看docker,想弄明白它究竟有什么功能,能用在什么地方,然后就去官网上看了下它的用户指南,按照其内容自己整理了一份笔记,其中可能会有错误,望大家多多指教。
docker用户指南网址:http://docs.docker.com/userguide/
=====1.在一个docker容器中运行应用=====
1)在容器中运行一次输出“Hello world”
docker run ubuntu:14.04 /bin/echo 'Hello world'
#docker run 就是运行容器
#之后需要指定一个image,这里是ubuntu:14.04
#若本地有image就直接用,若docker找不到就到Docker Hub上下载一个。
#之后就是在容器里运行的命令了,输出Hello world

2)交互式的容器
docker run -t -i ubuntu:14.04 /bin/bash         #进入容器的bash
#-t 表示在新的容器里分配一个虚拟终端
#-i 表示允许我们用一个交互式的连接

3)后台运行容器
docker run -d ubuntu:14.04 /bin/sh -c
"while true; do echo hello world; sleep 1; done"
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147 #返回该容器的id。
#-d 表示让docker运行一个容器并放到后台执行。
docker ps          #返回正在运行的容器以及其运行的应用等信息
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1e5535038e28 ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage

#container id就是容器的短id;ports name是自动生成的该容器的名字,只要开启一个容器,docker就会给它去一个名字。
docker logs insane_babbage    #查看容器里面的标准输出,后面跟上容器名
hello world
hello world
hello world
. . .
docker stop insan_babbage    #停止运行的docker容器,成功的话会返回该容器的名字


===========2.docker容器============

1)docker命令
命令格式:[sudo]docker [flags] [command] [arguments] ..
eg.
docker run -i -t ubuntu /bin/bash
查看docker版本
docker version    #docker client和docker server都会有,还有go语言版本,以及git的版本


2)查看docker客户端的功能
docker
Usage:docker [OPTIONS] COMMAND [arg...]
-H=[unix:///var/run/docker.sock]: tcp://host:port to bind/connect to or unix://path/to/socket to use

A self-sufficient runtime for linux containers.

Commands:
attach Attach to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders from the containers filesystem to the host path
diff Inspect changes on a container's filesystem
events Get real time events from the server
export Stream the contents of a container as a tar archive
history Show the history of an image
images List images
import Create a new filesystem image from the contents of a tarball
info Display system-wide information
inspect Return low-level information on a container
kill Kill a running container
load Load an image from a tar archive
login Register or Login to thedocker registry server
logs Fetch the logs of a container
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
pause Pause all processes within a container
ps List containers
pull Pull an image or a repository from thedocker registry server
push Push an image or a repository to thedocker registry server
restart Restart a running container
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save an image to a tar archive
search Search for an image in thedocker index
start Start a stopped container
stop Stop a running container
tag Tag an image into a repository
top Lookup the running processes of a container
unpause Unpause a paused container
version Show thedocker version information
wait Block until a container stops, then print its exit code

3)查看docker命令的用法
dicker command [--help]


4)在docker里面运行一个网页应用
docker run -d -P training/webapp python app.py
-d 后台运行一个容器
-P 从容器映射所有需要的端口到宿主机
#training/webapp是一个已经创建好的包含一个简单的python flask web 应用的容器,其开放5000端口供客户端访问
#由于本地没有,自行从docker hub上下载,所以执行这条命令需要保证能够联网

5)查看web应用容器
docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a2243aabeef training/webapp:latest python app.py 9 seconds ago Up 8 seconds 0.0.0.0:49154->5000/tcp trusting_archimedes
-l 返回最近一个容器的详细信息
-a 查看已经停止的容器的信息

其中ports部分,是在我们通过docker run的-P选项来映射image中开启的端口到宿主机上。这里是将docker容器中的开放端口(5000端口)映射到了宿主机的49154端口。




网络端口映射在docker中是可配置的。-P在这里其实等价于-p 5000(这个应用就是开放5000端口),使得容器中的5000端口映射到宿主机上的49000~49900端口上。在run的时候也可以直接使用-p选项来映射:
docker run -d -p 5001:5000 training/webapp python app.py
这里就是将另一个容器的5000端口映射到宿主机的5001端口。


注:访问的是另一个容器的5000端口

6)快速查看网络端口
docker port [name|ID] 容器端口
eg.
docker port jolly_fermi 5000
0.0.0.0:49200

7)查看web应用的日志
docker logs [-f] [name|ID]
-f 查看容器的标准输出
docker logs -f jolly_fermi
* Running on http://0.0.0.0:5000/ 192.168.125.1 - - [09/Jul/2014 11:50:47] "GET /favicon.ico HTTP/1.1" 404 -
192.168.125.1 - - [09/Jul/2014 11:50:47] "GET / HTTP/1.1" 200 -
192.168.125.1 - - [09/Jul/2014 11:50:47] "GET / HTTP/1.1" 200 -

8)查看web应用容器的进程
docker top [name|ID]
eg.
docker top jolly_fermi
UID PID PPID C STIME TTY TIME CMD
root 2338 1173 0 19:50 ? 00:00:02 python app.py

9)检查web应用容器配置
docker inspect jolly_fermi
[{
"Args": [
"app.py"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"python",
"app.py" ...
也可以指定一个元素来查看
docker inspect -f '{{ .Config.Cmd }}' jolly_fermi
[python app.py]

10)停止web应用容器
 docker stop jolly_fermi


11)重启web应用容器
 docker start jolly_fermi
#docker attach jolly_fermi,若该容器可以进入的话,这句就是连到容器里面。

12)删除web应用容器
    docker rm jolly_fermi


=======3.docker镜像(images)=======

管理和使用本地的docker镜像
创建一个基本的镜像
上传镜像到docker hub

1)列出本地镜像
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos latest 0c752394b855 4 weeks ago 124.1 MB
training/webapp latest 31fa814ba25a 5 weeks ago 278.6 MB
这些都是从docker hub上下载的
每个repository都可能有多个不同的镜像,如centos:6.5,centos:6.4。这些都是取决于在pull镜像的时候所下载的镜像。
所以在运行一个镜像的时候需要加上后面的TAG标签,如:
docker run -t -u ubuntu:14.04 /bin/bash
若不添加这个标签,docker就是用latest这个标签的镜像。

2)获取一个新的镜像
docker pull 镜像名
eg.
docker pull ubuntu


3)找镜像
(1)可以直接上官网找




(2)通过命令行来找
docker search 镜像名
eg.
docker search sinatra
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
training/sinatra                       Sinatra training image                          0                    [OK]
marceldegraaf/sinatra                  Sinatra test app                                0
mattwarren/docker-sinatra-demo                                                         0                    [OK]
luisbebop/docker-sinatra-hello-world                                                   0                    [OK]
bmorearty/handson-sinatra              handson-ruby + Sinatra for Hands on with D...   0
subwiz/sinatra                                                                         0
bmorearty/sinatra                                                                      0. . .
#列表中有名字、描述、星值(类似“赞”)、官方、自动创建(可以去扩充)。

4)从docker hub上拖“我们”的镜像
docker pull training/sinatra
然后团队就可以用自己的镜像了
docker run -t -i training/sinatra


5)创建我们自己的镜像
下载的镜像可能不能完全满足自身的需要,需要做一些改动。有两个方法可以更新和创建镜像
(1)通过更新容器并同步到一个镜像中
(2)通过Dockerfile来指定创建镜像

6)更新并提交一个镜像(5)的方法一)
(1)通过该镜像创建一个容器
docker run -t -i centos /bin/bash
bash-4.1#
在这个镜像没有标出其容器的ID,可以通过docker ps查看到是08b6d2e3c87e

(2)在容器里通过yum安装vim和httpd并退出容器
yum -y install httpd vim
exit
#这里通过centos的base的repo成功联网安装。
很好奇docker 的容器网络设置,后来发现,docker的容器使用的是nat的方法,docker生成容器的同时,宿主机上会创建与容器联通的一个虚拟网卡,然后docker 的容器就可以通过这个网卡来联网了。类似于vmware的nat。
宿主机上的操作:
[root@localhost ~]# ifconfig
docker0 Link encap:Ethernet HWaddr 46:D4:FB:67:3B:36
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::5817:1ff:fe25:615d/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13852 errors:0 dropped:0 overruns:0 frame:0
TX packets:23720 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:565006 (551.7 KiB) TX bytes:28907343 (27.5 MiB)
...
docker容器:
bash-4.1# traceroute www.baidu.com
bash-4.1# traceroute www.baidu.com
traceroute to www.baidu.com (180.97.33.71), 30 hops max, 60 byte packets1 172.17.42.1 (172.17.42.1) 0.040 ms 0.012 ms 0.010 ms2 192.168.125.2 (192.168.125.2) 0.108 ms 0.080 ms 0.077 ms3 * * *4 * * * (3)现在已经有了这个与基本的镜像不同的容器,通过commit来创建镜像
docker commit -m="Added vim and httpd" -a="liuling"
08b6d2e3c87e myown/centos:v1
-m 描述信息
-a 操作者
后面跟容器的id,以及镜像的标签。
其中myown是只用户,centos是镜像名,后面的v2是版本
(4)查看刚才建立的镜像
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEmyown/centos v1 1ab425143ef8 3 minutes ago 260.3 MB
7)通过Dockerfile创建镜像(从头做一个新的镜像)
mkdir centos
cd centos
vi Dockerfile
# make /data directory and yum install vsftpd
FROM myown/centos:v1
MAINTAINER liuling
RUN mkdir /data
RUN yum -y install vsftpd

docker build -t="myown/centos:v2" .    #docker build -t=“镜像名”dockerfile的路径,注意这里有一个“.”
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM myown/centos:v1
---> 1ab425143ef8
Step 1 : MAINTAINER liuling
---> Using cache
---> b977f42fb08c
Step 2 : RUN mkdir /data
---> Using cache
---> 80d492289b95
Step 3 : RUN yum -y install vsftpd
---> Running in a742917e9b67
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.ustc.edu.cn
...
Complete!
---> 14f9e7b5be23
Removing intermediate container a742917e9b67
Successfully built 14f9e7b5be23
这里是使用build命令,-t指定镜像归属/名:标签,后面通过"."来指定Dockerfile的所在路径。
通过Dockerfile创建文件,首先发送给docker daemon。其实就是建立一个容器,执行一条命令,然后commit出一个镜像,再使用这个镜像建立一个容器,再执行一条命令,再commint出一个镜像。最后命令执行完毕,commit出最后一个镜像,就将前面所有过渡用的容器删除。
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
myown/centos v2 14f9e7b5be23 2 minutes ago 292.8 MB

8)设置镜像的标签(版本)
docker tag [imageID] [username]/[repository name]:[new tag]
eg.
    docker tag 14f9e7b5be23 myown/centos:v3
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
myown/centos v2 14f9e7b5be23 36 minutes ago 292.8 MB
myown/centos v3 14f9e7b5be23 36 minutes ago 292.8 MB 这里就给myown/centos:v2添加了一个新的标签。(个人有点觉得像一个不同标签名的快捷方式0.0)

9)将镜像上传到Docker Hub,分享给其他人
   docker push myown/centos


10)删除本地的镜像
docker rmi myown/centos:v3
Untagged: myown/centos:v3
#由于这个是添加的标签,因此会有untagged,即取消标签
docker rmi myown/centos:v2
Error: Conflict, cannot delete d47258e47dc3 because the container bae61e4726e4 is using it (docker untagged the image), use -f to force
2014/07/10 18:47:59 Error: failed to remove one or more images #若该镜像上面已经创建了容器,是不能够直接删除的,需要先删除容器
docker rm bae61e4726e4
bae61e4726e4
#由于第一次删除的时候虽然没有成功,但是名字和tag已经没了,就只有通过id来删除了。
docker rmi 14f9e7b5be2
Deleted: d47258e47dc3310ab857c44a818c0112a2784674b5dc9f3dbd3075db141322a1
Deleted: c8d2bc86f41e11e529e204af5f47876d5a7f72cbcfd8af00a6910af375858e02
Deleted: eaee52520045a1e3d39f260bd5d7fe40fa750fab5e541269deae6bdea4a40d73

=======4.将容器连接在一起=======

1)网络端口映射
docker run -d -P training/webapp pyton app.py
#使用-P则表示将容器内的端口随机映射到宿主机端口(49000~49900)。
注:容器中是有一个内网以及内网端口(可以通过docker inspect来查看容器的ip地址)。
可以通过docker ps 来查看端口映射“宿主机端口->容器端口”
docker ps training/webapp
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7b1263fa1f7 training/webapp:latest python app.py 10 seconds ago Up 8 seconds 0.0.0.0:49153->5000/tcp sick_nobel

通过-p指定端口映射规则

docker run -d -p 49000:5000 training/webapp python app.py
#将容器的5000端口与宿主机的49000端口映射出去,但这并不是一个好方法,因为一个-p只能让一个容器使用一个端口,而-P则是使用将容器的所有开放端口映射出去。

上面两种方法都是开发端口给所有用户(所有能连到该host的用户都可以访问),通过-p还可以指定只允许本地(宿主host)访问端口49000来访问web应用。
docker run -d -p 127.0.0.1:49000:5000 training/webapp python app.py
#这里的127.0.0.1也可以改成localhost
elinks --dump 127.0.0.1:49000  #宿主机上测试
Hello world!

也可以不指定宿主机的端口让其随机选择
    docker run -d -p 127.0.0.1::5000 training/webapp python app.py
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad644d473938 training/webapp:latest python app.py 4 seconds ago Up 3 seconds 127.0.0.1:49155->5000/tcp determined_samme

还可以指定使用udp端口
    docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33a5ce0d825e training/webapp:latest python app.py 3 seconds ago Up 3 seconds 5000/tcp, 127.0.0.1:5000->5000/udp naughty_yonath
查看该容器5000端口映射到宿主机的端口
docker port naughty_yonath 5000/udp
127.0.0.1:5000
Note: The
-p
flag can be used multiple times to configure multiple ports.
#官网上的一句话,不过不知道怎样实现。

2)docker容器连接

网络端口映射不是唯一的方法让容器连接到其他。docker也有一个连接系统可以

3)容器命名

创建一个容器的时候docker会自动为容器命令,也可以自定义名字。
eg.
docker run -d -P --name web training/webapp python app.py
查看容器名字
docker ps -l
docker inspect -f "``.`Name`" 容器id
容器名必须唯一。
若想只用一次容器,可以再docker run 的选项中加上--rm,退出容器之后就会删除该容器了。

4)容器连接
创建一个名为db的容器(包含PostgreSQL数据库)
docker run -d --name db training/postgres
创建一个新的网页容器并且link到db容器
docker run -d -P --name web --link db:db training/webapp python app.py
其中,--link name:alias,name是连接到得容器名,alias是连接的别名。
docker ps
$docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d3af77b76eb training/webapp:latest python app.py 3 seconds ago Up 2 seconds 0.0.0.0:49153->5000/tcp web
cfad1bb78495 training/postgres:latest su postgres -c '/usr 27 seconds ago Up 27 seconds 5432/tcp db,web/db
我们可以发现连接给db和web这两个容器创建了一个父-子关系。父容器(db)可以再子容器中连接信息。容器建立了一个安全的通道而不是一个公开一个端口。
docker在子容器里通过两种方法为父容器公开一个连接的信息:
a)环境变量
b)更新/etc/hosts文件

可以看docker的初始化环境变量的设置。通过env命令来列出容器的环境变量
docker run --rm --name web2 --link db:db training/webapp env
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5000_TCP=tcp://172.17.0.5:5432
DB_PORT_5000_TCP_PROTO=tcp
DB_PORT_5000_TCP_PORT=5432
DB_PORT_5000_TCP_ADDR=172.17.0.5
. . .
注意:这些环境变量只是在容器的第一个进程中使用。一些进程(sshd)为了连接而生成新的shell将会清除掉这些环境变量。

上面的变量都是DB_开头的,这个是连接的alias,连接的名字是什么,上面变量就是以什么来开头的。我们可以使用这些环境变量来配置应用去连接在db容器中的数据库。这个连接时安全、私有并且只有web容器才能够与db容器通信。

除了环境变量之外,docker在子容器中为连接父节点而在/etc/hosts添加一个入口。(不能够随意修改/etc/hosts这个文件。)

docker run -t -i --name web1 --link db:db training/webapp /bin/bash
root@6148503e55de:/opt/webapp# cat /etc/hosts
172.17.0.11 6148503e55de
...
172.17.0.9 db

尝试ping一下db(由于python的webapp这个容器没有ping命令,需要安装)
root@6148503e55de:/opt/webapp#apt-get install -yqq inetutils-ping
root@6148503e55de:/opt/webapp# ping db
PING db (172.17.0.9): 48 data bytes
56 bytes from 172.17.0.9: icmp_seq=0 ttl=64 time=2.884 ms
56 bytes from 172.17.0.9: icmp_seq=1 ttl=64 time=0.068 ms
56 bytes from 172.17.0.9: icmp_seq=2 ttl=64 time=0.069 ms
56 bytes from 172.17.0.9: icmp_seq=3 ttl=64 time=0.069 ms

=======5.在容器中管理数据=======

1)data volumes(数据卷)

数据卷是一个在一个活多个容器里特别设计的目录,围绕union file system来提供多个持久的或共享数据的特性:
a)data volumes可以被多个容器共享和重用
b)可以直接修改在dota volumes进行变动
c)变动data volumes不包括更新一个镜像
d)volumes将一直存在知道没有容器使用它们

2)添加一个data volumes
    docker run -t -i --name centos1 -v /mingchao centos /bin/bash
bash-4.1# df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 10321208 300112 9496808 4% /
/dev/mapper/docker-253:0-132071-7020c1bf4840f24a984f12587a08f9bb2f5ec0f40e8fe0b1e8ded18c3b631c17
10321208 300112 9496808 4% /
tmpfs 957244 0 957244 0% /dev
shm 65536 0 65536 0% /dev/shm
/dev/mapper/VolGroup-lv_root
36744792 4333084 30545164 13% /.dockerinit
/dev/mapper/VolGroup-lv_root
36744792 4333084 30545164 13% /etc/resolv.conf
/dev/mapper/VolGroup-lv_root
36744792 4333084 30545164 13% /etc/hostname
/dev/mapper/VolGroup-lv_root
36744792 4333084 30545164 13% /etc/hosts
/dev/mapper/VolGroup-lv_root
36744792 4333084 30545164 13% /mingchao
tmpfs 957244 0 957244 0% /proc/kcore
这里是创建了一个新的volume在容器的/mingchao下。
注:也可以通过在Dockerfile文件中使用VOLUME这个命令来添加一个或多个volumes使得所有用该镜像创建的容器都可以使用。

3)挂载一个宿主机目录当做data volumes
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
这里是将本地的/src/webapp目录挂载到容器的/opt/webapp目录中。
注:这个不能通过Dockerfile来使用。

docker默认是实现可读可写的volume,不过我们也可以自定义为只读
docker run -d -P --name web -v /src/webapp:/opt/webapp:ro tra
ining/webapp python app.py


4)创建和挂载一个data volume 容器(容器挂载另一个容器的data volume)

如果有需要保存的数据并且在容器中共享,或者被一些不长久使用的容器使用,最好是创建一个data volume的容器,然后再使用它的时候采取挂载。

#创建一个容器,并且里面创建一个data volume。
docker run -i -t -v /dbdata --name dbdata centos /bin/bash


#创建另一个容器,挂载dbdata的data volume----/dbdata
docker run -i -t --volumes-from dbdata(容器名) --name db1 centos /bin/bash


#创建第二个容器来挂载dbdata的data volume
docker run -i -t --volumes-from dbdata --name db2 centos /bin/bash


这种挂载可以继续传递下去:
docker run -i -t --volumes-from db1 --name db3 centos /bin/bash
如果删除了其中的一些容器,甚至是一开始创建的dbdata这个容器,该volume都会存在,直到所有挂载volume的容器都删除掉,这个volume才会被删除掉。

5)data volumes备份、恢复或迁移
docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
这里我们启动一个新的容器然后挂载dbdata容器的volume。接着挂载一个当前host的路径到/backup。最后,我们使用tar来将dbdata的volume备份到backup.tar(在/backup目录中,即是宿主机的当前目录)。当命令结束且容器停止了之后我们就获得了dbdata的volume的备份。

可以将它恢复到相同的容器中,或者其他的任何地方。
 docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
docker run --volumes-from dbdata2 -v $(pwd):/backup centos tar xvf /backup/backup.tar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  镜像 容器 docker