1. 运行容器
sudo run -i -t ubnutu /bin/bash
Docker
执行 docker run
命令,并指定了-i
和-t
两个命令行参数,告诉Docker
为新创建的容器提供一个交互式shell
。其中 ubuntu
镜像是一个常备镜像,也可以成为"基础"(base)镜像,它由docker
公司提供,保存在Docker Hub Registry
上。 常用的 docker run 容器命令选项有:
-i
:表示以交互模式运行容器,通常与-t
结合使用
-t
:为容器重新分配一个伪输入终端,通常与-i
结合使用
-d
:后台运行容器,并返回容器 ID,即启动守护式容器 (这样创建的容器不会分配一个伪输入终端,如果是以-it
两个参数启动,启动后则会分配一个伪输入终端)
-p
:指定端口映射,格式为:-p 主机(宿主机)端口:容器映射端口
,可以使用多个-p
做多个端口映射
-v
:指定挂载主机目录 / 文件 到容器目录 / 文件 上,即挂载容器数据卷,格式为:-v 主机(宿主机)目录/文件的绝对路径:容器内目录/文件的绝对路径[:读取权限]
,可以使用多个-v
做多个目录或文件映射,默认为rw读写模式
,ro表示只读
。
rw读写模式
:表示宿主机能对数据卷进行读取和更改,容器也能对其进行读取和更改。
ro表示只读
:表示宿主机能对数据卷进行读取和更改,容器只能对其进行读取不能更改。
--name
:为创建的容器指定一个名称,格式为:--name=容器名称
2. 查看所有容器
sudo docker ps -a
,其中docker ps
只能看到正在运行的容器。
3. 容器命名
sudo docker run --name bob_the_container -i -t ubuntu /bin/bash
4. 启动容器 | 重启容器
启动容器: sudo docker start bob_the_container
重启容器: sudo docker restart aa3f365f0f4e
5. 进入正在运行的容器内并以命令行交互
bash
//以exec方式进入到容器
docker exec -it 容器ID/容器名称 /bin/bash 或 /bin/sh
//以attach方式进入到容器
docker attach 容器ID/容器名称
//如果不想进入容器,直接获取相关指令的运行结果,可在后面填写相关操作指令
docker exec -it 容器ID/容器名称 相关命令
exec 与 attach 的区别:
-
exec
:是在容器中打开新的终端,并且可以启动新的进程 (推荐) -
attach
:是直接进入容器启动命令的终端,不会启动新的进程sudo docker attach bob_the_container
附着在容器上,然后就又重新回到了容器的Bash
提示符,如下所示。
root@aa3f365f0f4e:/#
6. 获取容器日志
sudo docker logs daemon
获取容器日志,可以在命令后使用-f
参数来监控Docker
的日志。(提示:可以通过Ctrl+C
退出日志跟踪)
sudo
hello word
hello word
hello word
···
我们也可以跟踪容器日志的某一片段,和之前类似,只需要在tail
命令后加入-f--lines
标志即可。例如可以用docker logs --tail 10 daemon_dave
获取日志的最后10行内容。另外也可以用docker logs --tail 0 -f daemon_dave
命令来跟踪某个容器的最新日志而不必读取整个日志文件。为了让调试更简单,我们还可以使用-t
标志为某条日志项加上时间戳,如下所示:\
csharp
$ sudo docker logs -ft daemon_dave
[May 10 13:06:17.934] hello world
[May 10 13:06:18.935] hello world
[May 10 13:06:19.937] hello world
[May 10 13:06:20.939] hello world
[May 10 13:06:21.942] hello world
···
7. 查看容器映射端口号
查看容器已公开的 80端口映射到了哪个端口。
makefile
$ sudo docker port 09a570cc2267 80
0.0.0.0:49160
8. 查看容器内的进程
css
$ sudo docker top daemon_dave
该命令执行后,我们可以看到容器内的所有进程(主要还是我们的while循环)、运行进程的用户及进程ID,如下所示:
bash
PID USER COMMAND
977 root /bin/sh -c while true; do echo hello world; sleep 1; done
1123 root sleep 1
9. 在容器内部运行进程,我们可以通过docker exec
命令在容器内部额外启动新进程。可以在容器内运行的进程有两种类型:后台任务和交互式任务。
后台任务:
shell
$ sudo docker exec -d daemon_dave touch /etc/new_config_file
交互式任务:
shell
$ sudo docker exec -t -i daemon_dave /bin/bash
10. 停止守护式容器
docker stop
命令向docker
容器进程发生SIGTERM
信号。如果你想快速停止某个容器,也可以使用docker kill
命令来向容器进行发送SIGKILL
信号。
arduino
$ sudo docker stop daemon_dave
要想查看已经停止的容器的状态,则可以使用docker ps
命令。还有一个很实用的命令docker ps -n x
,该命令会显示最后x
个容器,不论这些容器正在运行还是已经停止。
11. 自动重启容器:--restart
默认的行为是Docker
不会重启容器。
ini
$ sudo docker run --restart=always --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
在本例中,--restart
标志被设置为always
。无论容器的退出代码是什么,Docker
都会自动重启该容器。除了always
,我们还可以将这个标志设为on-failure
,这样,只有当容器的退出代码为非0值的时候,才会自动重启。另外,on-failure
还接受一个可选的重启次数参数,如下所示:
ini
--restart=on-failure:5
这样,当容器退出代码为非0时,Docker
会尝试自动重启该容器,最多重启5次。
12. 深入容器
ruby
$ sudo docker inspect daemon_dave
13. 删除容器
shell
$ sudo docker rm 80430f8d0921
需要注意的是,运行中的Docker
容器是无法删除的!你必须先通过docker stop
或docker kill
命令停止容器,才能将其删除。
一次性删除全部容器:
css
docker rm `docker ps -a -q`
14. 列出镜像
ruby
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest c4ff7513909d 6 days ago 225.4 MB
本地镜像都保存在Docker
宿主机的/var/lib/docker
目录下。每个镜像都保存在Docker
所采用的存储驱动目录下面,如aufs
或者devicemapper
。也可以在/var/lib/docker/containers
目录下面看到所有的容器。
镜像从仓库下载下来。镜像保存在仓库中,而仓库存在于Registry
中。默认的Registry
是有Docker
公司运营的公共Registry
服务,即Docker Hub
。
在Docker Hub
(或者你自已运营的Registry
)中,镜像是保存在仓库中的。可以将镜像仓库想象为类似Git
仓库的东西。它包括镜像、层以及关于镜像的元数据(metadata)。
15. 查找镜像
我们可以通过docker search
命令来查找所有Docker Hub
上公共的可用镜像,如下所示:
bash
$ sudo docker search puppet
NAME DESCIRPTIOM STARS OFFICIAL AUTOMATED
wfarr/puppet-module...
jamtur01/puppetmaster
...
也可以在Docker Hub
网站上在线查找可用镜像。
让我们从上面的结果中拉取一个镜像:
shell
$ sudo docker pull jamtur01/puppetmaster
这条命令会下载jamtur01/puppetmaster
镜像到本地(这个镜像里预装了Puppetmaster)。
接着就可以用这个镜像构建一个容器了。下面就用docker run
命令来构建一个容器。
ini
$ sudo docker run -i -t jamtur01/puppetmaster /bin/bash
root
architecture => amd64
augeasversion => 1.2.0
...
root@4655dee672d3:/# puppet --version
3.4.3
可以看到,我们已经从jamtur01/puppetmaster
镜像启动了一个新容器。我们一交互式的方式启动了该容器,并且在里面运行了Bash shell
。
16. 构建镜像
- 使用
docker commit
命令
ruby
$ sudo docker run -i -t ubuntu /bin/bash
root@4aab3ce3cb76:/#
接下来,在容器中安装Apache
,如下所示:
ruby
root@4aab3ce3cb76:/# apt-get -yqq update
...
root@4aab3ce3cb76:/# apt-get -y install apache2
...
我们启动了一个容器,并在里面安装了Apache
。我们会将这个容器作为一个Web
服务器来运行,所有我们想把它的当前状态保存下来。这样就不必每次都创建一个新容器并再次在里面安装Apache
了。为了完成此项工作,需要先使用exit
命令从容器里退出,之后再运行docker commit
命令,代码如下所示:
shell
$ sudo docker commit 4aab3ce3cb76 jamtur01/apache2
8ce0ea7a1528
- 使用
docker build
命令和Dockerfile
文件
现在我们并不推荐使用docker commit
命令,而应该使用更灵活、更强大的 Dockerfile
来构建Docker
镜像。\
17. Dockerfile指令:
- CMD
CMD
指令用于指定一个容器启动时要运行的命令。类似于RUN
指令,只是RUN
指令是指定镜像被构建时要运行的命令,而CMD
是指容器被启动时要运行的命令。这和使用docker run
命令启动容器时指定要运行的命令非常类似,比如代码清单:
shell
$ sudo docker run -i -t jamtur01/static_web /bin/true
可以认为代码清单所示的命令和在Dockerfile
中使用如下代码所示的CMD
指令是等效的。
css
CMD ["/bin/true"]
- ENTRYPOINT
ENTRYPOINT
是指定容器启动时要执行的可执行文件或脚本,并且该命令在运行容器时不能被覆盖。ENTRYPOINT
可以看作是容器的默认执行命令,它会在运行容器时自动执行。如果在运行容器时指定了其他命令,则这些命令将作为ENTRYPOINT
命令的参数传递给容器。
例如,在Dockerfile
中指定ENTRYPOINT
为一个可执行文件,如下所示:
css
ENTRYPOINT ["./app"]
在运行容器时可以使用以下命令:
arduino
docker run myapp arg1 arg2
这样将运行容器,自动执行ENTRYPOINT
命令"./app"
,并将"arg1"
和"arg2"
作为参数传递给它。
CMD
是指定容器启动时要执行的默认命令或参数。它可以被覆盖,如果在运行容器时指定了其他命令,则这些命令将替换掉CMD
命令。
例如,在Dockerfile
中指定CMD
为一个默认参数,如下所示:
css
CMD ["--port", "80"]
在运行容器时可以使用以下命令:
arduino
docker run myapp --port 8080
这样将运行容器,并使用"--port 8080"
替换掉默认的CMD
命令参数"--port 80"
。
总结来说,ENTRYPOINT
是指定容器启动时要执行的默认命令,它在运行容器时不能被覆盖。而CMD
是指定容器启动时要执行的默认命令参数,它可以被覆盖。通常情况下,ENTRYPOINT
用于指定容器启动时要运行的应用程序,而CMD
用于指定应用程序的默认参数。
- WORKDIR
WORKDIR
指令用来在镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT
和CMD
指定的程序会在这个目录下执行。
bash
WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPORT [ "rackup" ]
这里,我们将工作目录切换为/opt/webapp/db
后运行了bundle install
命令,之后又将工作目录设置为/opt/webapp
,最后设置了ENTRYPOINT
指令来启动rackup
命令。
可以通过-w
标志在运行时覆盖工作目录,如代码所示:
bash
$ sudo docker run -ti -w /var/log ubuntu pwd
/var/log
该命令会将容器内的工作目录设置为/var/log
。
- ENV
ENV
指令用来在镜像构建过程中设置环境变量,如代码所示:
arduino
ENV RVM_PATH /home/rvm/
我们也能在其他指令中直接使用这些环境变量。
bash
ENV TARGET_DIR /opt/app
WORKDIR $TARGET_DIR
这里我们设定了一个新的环境变量TARGET_DIR
,并在WORKDIR
中使用了它的值。因此实际上WORKDIR
指令的值会被设为opt/app
。
- USER
USER
指令用来指定该镜像会以什么样的用户去运行,如代码所示:
sql
USER nginx
-
VOLUME
VOLUME
指令用来向基于镜像创建的容器添加卷。卷功能让我们可以将数据(如源代码)、数据库或者其他内容添加到镜像中而不是将这些内容提交到镜像中,并且允许我们在多个容器间共享这些内容。 -
ADD
ADD
指令用来将构建环境下的文件和目录复制到镜像中。在ADD
文件时,Docker
通过目的地址参数末尾的字符来判断文件源是目录还是文件。如果目标地址以/
结尾,那么Docker
就认为源位置指向的是一个目录。如果目的地址不是以/
结尾,那么Docker
就认为源位置指向的是文件。最后指的一提的是,
ADD
在处理本地归档文件(tar arhive)时还有一些小魔法。如果将一个归档文件(合法的归档文件包括gzip
、bzip2
、xz
)指定为源文件,Docker
会自动将归档文件解开(unpack
)。 -
COPY
COPY
指令非常类似于ADD
,它们根本的不同是COPY
只关心构建上下文中复制本地文件,而不会去做文件提取(extraction
)和解压(decompression
)的工作。
javascript
COPY conf.d/ /etc/apache2/
这条指令将会把本地conf.d
目录中的文件复制到/etc/apache2
目录中。
- ONBUILD
ONBUILD
指令能为镜像添加触发器(trigger
)。
触发器会在构建过程中插入新指令,我们可以认为这些指令是紧跟在FROM
之后指定的。触发器可以是任何构建指令,比如代码所示:
bash
ONBUILD ADD . /app/src
ONBUILD RUN cd /app/src && make
上面的代码会在构建镜像中加入ONBUILD
触发器,ONBUILD
指令可以在镜像上运行docker inspect
命令来查看:
ruby
$ sudo docker inspect 508efa4e4bf8
···
"OnBuild":[
"ADD . /app/src",
"RUN cd /app/src && make"
]
...