in Docker Linux ~ read.

玩转Docker之常用命令篇(三)

首先我们来解决一个小问题,使用docker每次都要用sudo,为了让非root用户使用docker,可将当前用户添加到docker用户组:

sudo groupadd docker  
sudo gpasswd -a ${USER} docker  # 当前用户添加到docker group  

然后重新登入下用户就可以直接使用docker命令了。

一、查看docker信息及帮助

# 查看docker版本
 docker version

# 显示docker系统的信息
 docker info

# 所有Docker命令帮助
 docker help 

二、镜像操作

# 检索image
 docker search image_name

# 下载image
 docker pull image_name

# 列出镜像列表; -a, --all=false Show all images; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
 docker images

# 删除一个或者多个镜像; -f, --force=false Force; --no-prune=false Do not delete untagged parents
 docker rmi image_name

# 显示一个镜像的历史; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
 docker history image_name

# 保存镜像到一个tar包; -o, --output="" Write to an file
 docker save image_name -o file_path
# 加载一个tar包格式的镜像; -i, --input="" Read from a tar archive file
 docker load -i file_path

# 机器a
 docker save image_name > /home/save.tar
# 使用scp将save.tar拷到机器b上,然后:
 docker load < /home/save.tar

三、容器操作

1.启动容器

# 在容器中运行"echo"命令,输出"hello word"
 docker run image_name echo "hello word"

# 交互式进入容器中
 docker run -i -t image_name /bin/bash


# 在容器中安装新的程序
 docker run image_name apt-get install -y app_name

# 运行一个新容器,同时为它命名、端口映射、文件夹映射。以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  

-d:以守护进程方式运行(后台),并返回容器ID; -P:默认匹配docker容器的5000端口号到宿主机的49153 to 65535端口 -p ::指定端口号 --name: 指定容器的名称 --rm:退出时删除容器 -a stdin 指定标准输入输出内容类型,可选 STDIN/STDOUT / STDERR 三项; -i 以交互模式运行容器,通常与 -t 同时使用; -t 为容器重新分配一个伪输入终端,通常与 -i 同时使用; --dns 8.8.8.8 指定容器使用的DNS服务器,默认和宿主一致; --dns-search example.com 指定容器DNS搜索域名,默认和宿主一致; -h "mars" 指定容器的hostname; -e username="ritchie" 设置环境变量; --env-file=[] 从指定文件读入环境变量; --cpuset="0-2" or --cpuset="0,1,2" 绑定容器到指定CPU运行;

2.查看容器

# 列出当前所有正在运行的container
 docker ps
# 列出所有的container
 docker ps -a
# 列出最近一次启动的container
 docker ps -l

3.修改容器

# 保存对容器的修改; -a, --author="" Author; -m, --message="" Commit message
 docker commit ID new_image_name

4.容器其它基本操作

# 删除所有容器
 docker rm `docker ps -a -q`

# 删除单个容器; -f, --force=false; -l, --link=false Remove the specified link and not the underlying container; -v, --volumes=false Remove the volumes associated to the container
 docker rm Name/ID

# 停止、启动、杀死一个容器
 docker stop Name/ID
 docker start Name/ID
 docker kill Name/ID

# 从一个容器中取日志; -f, --follow=false Follow log output; -t, --timestamps=false Show timestamps
 docker logs Name/ID

# 列出一个容器里面被改变的文件或者目录,list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的
 docker diff Name/ID

# 显示一个运行的容器里面的进程信息
 docker top Name/ID

# 从容器里面拷贝文件/目录到本地一个路径
 docker cp Name:/container_path to_path
 docker cp ID:/container_path to_path

# 重启一个正在运行的容器; -t, --time=10 Number of seconds to try to stop for before killing the container, Default=10
 docker restart Name/ID

# 附加到一个运行的容器上面; --no-stdin=false Do not attach stdin; --sig-proxy=true Proxify all received signal to the process
 docker attach ID

四、镜像仓库操作

# 登陆registry server; -e, --email="" Email; -p, --password="" Password; -u, --username="" Username
 docker login

# 发布docker镜像
 docker push new_image_name

五、网络管理

 docker run -P:随机分配端口号
 docker run -p 5000:5000:绑定特定端口号(主机的所有网络接口的5000端口均绑定容器的5000端口)
 docker run -p 127.0.0.1:5000:5000:绑定主机的特定接口的端口号
 docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py:绑定udp端口号
 docker port <CONTAINER_ID> 5000:查看容器的5000端口对应本地机器的IP和端口号
# 使用Docker Linking连接容器:
 Docker为源容器和接收容器创建一个安全的通道,容器之间不需要暴露端口,接收的容器可以访问源容器的数据
 docker run -d -P --name <CONTAINER_NAME> --link <CONTAINER_NAME_TO_LINK>:<ALIAS>  

六、数据管理

Data Volumes:volume是在一个或多个容器里指定的特殊目录
- 数据卷可以在容器间共享和重复使用 - 可以直接修改容器卷的数据 - 容器卷里的数据不会被包含到镜像中 - 容器卷保持到没有容器再使用它

可以在容器启动的时候添加-v参数指定容器卷,也可以在Dockerfile里用VOLUMN命令添加

 docker run -d -P --name web -v /webapp training/webapp python app.py

也可以将容器卷挂载到宿主机目录或宿主机的文件上,<容器目录或文件>的内容会被替换为<宿主机目录或文件>的内容,默认容器对这个目录有可读写权限

 docker run -d -P --name web -v <宿主机目录>:<容器目录> training/webapp python app.py

可以通过指定ro,将权限改为只读

 docker run -d -P --name web -v <宿主机目录>:<容器目录>:ro training/webapp python app.py

在一个容器创建容器卷后,其他容器便可以通过--volumes-from共享这个容器卷数据,如下:

 docker run -d -v /dbdata --name db1 training/postgres echo Data-only container for postgres

首先启动了一个容器,并为这个容器增加一个数据卷/dbdata,然后启动另一个容器,共享这个数据卷

 docker run -d --volumes-from db1 --name db2 training/postgres

此时db2使用了db1的容器卷,当容器db1被删除时,容器卷也不会被删除,只有所有容器不再使用此容器卷时,才会被删除

 docker rm -v:删除容器卷

除了共享数据外,容器卷另一个作用是用来备份、恢复和迁移数据

 docker run --volumes-from db1 -v /home/backup:/backup ubuntu tar cvf /backup/backup.tar /dbdata

启动一个容器数据卷使用db1容器的数据卷,同时新建立一个数据卷指向宿主机目录/home/backup,将/dbdata目录的数据压缩为/backup/backup.tar

 docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
 docker run --volumes-from dbdata2 -v /home/backup:/backup busybox tar xvf /backup/backup.tar

启动一个容器,同时把backup.tar的内容解压到容器的backup

七、使用 Dockerfile 创建镜像

使用命令行的方式创建 Docker 镜像通常难以自动化操作。在更多的时候,我们使用 Dockerfile 来创建 Docker 镜像。Dockerfile 是一个纯文本文件,它记载了从一个镜像创建另一个新镜像的步骤。撰写好 Dockerfile 文件之后,我们就可以轻而易举的使用 docker build 命令来创建镜像了。

Dockerfile 非常简单,仅有以下命令在 Dockerfile 中常被使用:

命令 参数 说明
# - 注释说明
FROM <image>[:<tag>] 从一个已有镜像创建,例如ubuntu:latest
MAINTAINER Author <some-one@example.com> 镜像作者名字,如Max Liu <some-one@example.com>
RUN <cmd>或者['cmd1', 'cmd2'…] 在镜像创建用的临时容器里执行单行命令
ADD <src> <dest> 将本地的<src>添加到镜像容器中的<dest>位置
VOLUME <path>或者['/var', 'home'] 将指定的路径挂载为数据卷
EXPOSE <port> [<port>...] 将指定的端口暴露给主机
ENV <key> <value> 或者 <key> = <value> 指定环境变量值
CMD ["executable","param1","param2"] 容器启动时默认执行的命令。注意一个Dockerfile中只有最后一个CMD生效。
ENTRYPOINT ["executable", "param1", "param2"] 容器的进入点

下面是一个 Dockerfile 的例子:

# This is a comment
FROM ubuntu:14.04  
MAINTAINER Kate Smith <ksmith@example.com>  
RUN apt-get update && apt-get install -y ruby ruby-dev  
RUN gem install sinatra  

这里其他命令都比较好理解,唯独 CMDENTRYPOINT 我需要特殊说明一下。CMD 命令可用指定 Docker 容器启动时默认的命令,例如我们上面例子提到的 docker run -it ubuntu:latest sh -c '/bin/bash'。其中 sh -c '/bin/bash' 就是通过手工指定传入的 CMD。如果我们不加这个参数,那么容器将会默认使用 CMD 指定的命令启动。ENTRYPOINT 是什么呢?从字面看是进入点。没错,它就是进入点。ENTRYPOINT 用来指定特定的可执行文件、Shell 脚本,并把启动参数或 CMD 指定的默认值,当作附加参数传递给 ENTRYPOINT。

不好理解是吧?我们举一个例子:

ENTRYPOINT ['/usr/bin/mysql']  
CMD ['-h 192.168.100.128', '-p']  

假设这个镜像内已经准备好了 mysql-client,那么通过这个镜像,不加任何额外参数启动容器,将会给我们一个 mysql 的控制台,默认连接到192.168.100.128 这个主机。然而我们也可以通过指定参数,来连接别的主机。但是不管无论如何,我们都无法启动一个除了 mysql 客户端以外的程序。因为这个容器的 ENTRYPOINT 就限定了我们只能在 mysql 这个客户端内做事情。这下是不是明白了~

因此,我们在使用 Dockerfile 创建文件的时候,可以创建一个 entrypoint.sh 脚本,作为系统入口。在这个文件里面,我们可以进行一些基础性的自举操作,比如检查环境变量,根据需要初始化数据库等等。下面两个文件是我在日常工作的项目中添加的 Dockerfile 和 entrypoint.sh,仅供参考:

在准备好 Dockerfile 之后,我们就可以创建镜像了:

docker build -t starlight36/simpleoa .  

关于 Dockerfile 的更详细说明,请参考 https://docs.docker.com/reference/builder/

comments powered by Disqus