bingoogolapple / bingoogolapple.github.io

个人主页。同时也通过 Issues 记录学习笔记
http://www.bingoogolapple.cn
86 stars 22 forks source link

Docker学习笔记-基础三 #146

Open bingoogolapple opened 7 years ago

bingoogolapple commented 7 years ago

查看内核版本,需要在 3.10 及其以上

uname -a

检查 Device Magger

ls -l /sys/class/misc/device-mapper

安装 Docker 维护的版本

sudo apt-get update

https://get.docker.com/

curl -fsSL https://get.docker.com/ | sh

# 使用非 root 用户
sudo usermod -aG docker bingoogolapple
或
sudo groupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart

配置 DaoCloud 加速器

https://www.daocloud.io/mirror#accelerator-doc

# 需重启 Docker
sudo systemctl restart docker.service

以交互式启动容器

docker run -it --name test-ubuntu ubuntu bash

以交互方式重新启动容器

docker start -i test-ubuntu

以交互方式启动容器后,使进程在后台运行

先 ctrl + p
然后 ctrl + q

进入后台运行的容器

docker attach test-ubuntu

启动守护式容器

docker run -d --name test-ubuntu ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

查看容器运行日志

docker logs [-f] [-t] 容器名

-f --follows=true|false 默认为false,是否一直跟踪日志的变化并返回结果
-t --timestamps=true|false 默认为false,是否在返回的结果中加上时间戳
--tail  选择返回结尾处多少数量的日志,如果不知道会返回所有的日志,如果值为0,则显示最新的日志

docker logs -tf --tail 10 test-ubuntu

查看容器内进程

docker top 容器名

查看容器端口映射情况

docker port 容器名

在运行中的容器内启动新进程

docker exec [-d] [-i] [-t] 容器名 [COMMAND] [ARG...]

docker exec -it test-ubuntu bash
通过 ctrl+p 加 ctrl + q 使 bash 进程在后台运行
此时执行 docker top test-ubuntu 就能看到多了一个 bash 进程

停止守护式容器

# 发送信号给容器,等待容器停止,建议用这种方式
docker stop 容器名
#  会直接停止容器,不建议用这种方式
docker kill 容器名

使用 Docker 帮助文件

man docker-run
man docker-logs
man docker-top
man docker-exec

在容器中部署静态网站

docker run -p 8080:80 --name web -it ubuntu bash
apt-get update
apt-get install -y nginx
apt-get install -y vim
mkdir -p /var/www/html
cd /var/www/html
vim index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HelloWorld</title>
</head>
<body>
<p>HelloWorld</p>
</body>
</html>

whereis nginx         查看 nginx 安装目录
cd /etc/nginx/sites-enabled
vim default
修改 root 的值为 /var/www/html
nginx
ps -ef
先 ctrl + p 然后 ctrl + q,使容器在后台运行
docker port web        查看容器端口映射
docker inspect -f {{.NetworkSettings.IPAddress}} web     查看容器 ip 地址
curl http://localhost:8080
curl http://172.17.0.2
bingoogolapple commented 7 years ago

查看 Docker 安装信息


docker info

Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 3 Server Version: 1.12.6 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 7 Dirperm1 Supported: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: host overlay null bridge Swarm: inactive Runtimes: runc Default Runtime: runc Security Options: apparmor seccomp Kernel Version: 4.4.0-59-generic Operating System: Ubuntu 16.04.1 LTS OSType: linux Architecture: x86_64 CPUs: 4 Total Memory: 9.674 GiB Name: bingoogolapple ID: VE3P:R7HD:GPMQ:AB23:Z7CM:GVGO:2K77:PG5F:FOLW:XR5D:DVQN:642I Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ WARNING: No swap limit support Insecure Registries: 127.0.0.0/8

> Docker 的 CS 模式

➜ ~ nc -U /var/run/docker.sock GET /info HTTP/1.1

> 删除所有容器,-q 参数表示只返回容器 id

docker rm $(docker ps -aq)

> 删除 bga/test 仓库中的所有镜像,-q 参数表示只返回镜像 id

docker rmi $(docker images -q bga/test)

bingoogolapple commented 7 years ago

Docker 守护进程的配置与操作

查看守护进程

ps -ef | grep docker

查看 Docker 运行状态

sudo systemctl status docker

启动、停止、重启 docker

sudo service docker start
sudo service docker stop
sudo service docker restart

sudo systemctl stop docker.service
sudo systemctl start docker.service
sudo systemctl restart docker.service

启动配置文件 /etc/default/docker 已过时,通过 sudo systemctl status docker 能看到新版改成了 /lib/systemd/system/docker.service

# Docker Upstart and SysVinit configuration file

#
# THIS FILE DOES NOT APPLY TO SYSTEMD
#
#   Please see the documentation for "systemd drop-ins":
#   https://docs.docker.com/engine/articles/systemd/
#

# Customize location of Docker binary (especially for development testing).
# Docker 程序安装位置
#DOCKERD="/usr/local/bin/dockerd"

# Use DOCKER_OPTS to modify the daemon startup options.
# Docker 守护进程启动时的选项
#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"

# If you need Docker to use an HTTP proxy, it can also be specified here.
# 环境变量的设置
#export http_proxy="http://127.0.0.1:3128/"

# This is also a handy place to tweak where Docker's temporary files go.
#export TMPDIR="/mnt/bigdrive/docker-tmp"

Docker 的远程访问,保证 Client API 与 Server API 版本一致

增加 label

sudo vim /lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntuone -H fd://

sudo systemctl daemon-reload
sudo service docker restart

修改 Docker 守护进程启动选项 -H

tcp://host:port
unix:///path/to/socket
fd://* or fd://socketfd
守护进程默认配置为  -H fd://

改用 tcp 方式。使用纯 0 地址告诉服务器使用自身的 ip 地址来绑定,Docker 服务一般使用 2375 端口。这时就可以在浏览器中访问了 curl http://192.168.56.112:2375/info | grep Labels

ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H tcp://0.0.0.0:2375

但此时 docker info 就会执行不成功,必须 docker -H tcp://localhost:2375 info 这样才行,可以在配置文件中指定多个 -H 参数来解决这个问题。这样的话既能在远程访问,也能在本地直接访问

ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375

Docker 客户端配置选项和服务端一样 -H。服务端改成 tcp 方式后,客户端需要加上参数 docker -H tcp://192.168.56.111:2375 info

tcp://host:port
unix:///path/to/socket
fd://* or fd://socketfd
默认配置为  -H fd://

如果要平凡连接远程 Docker 服务端的话可以配置环境变量,这样在后续执行 Docker 命令时默认的就会连接到远程服务器上

export DOCKER_HOST="tcp://192.168.56.111:2375"

使用完了远程服务器后,将环境变量重置,Docker 客户端又会使用默认的链接方式来链接

export DOCKER_HOST=""
bingoogolapple commented 7 years ago

Dockerfile

即使在 Dockerfile 文件中通过 EXPOSE 暴露了端口,在使用镜像时也需要通过 -p 参数来指定容器的端口映射

# 注释
FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
RUN apt-get update
RUN apt-get install -y nginx
EXPOSE 80
# 在容器启动时运行 nginx,并且以前台的模式运行
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

通过 && 来减少一条 RUN 指令

FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
# 在容器启动时运行 nginx,并且以前台的模式运行
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

通过 Dockerfile 构建镜像,末尾的 . 表示 Dockerfile 所在目录的路径

docker build --tag bga/test:v1 .
docker build -t bga/test:v1 .

使用上一步构建的镜像来运行容器,默认执行的是 Dockerfile 里 CMD 指令指定的命令

docker run -p 80 --name cmd_test1 -d bga/test:v1

使用上一步构建的镜像来运行容器,指定容器运行时的命令,覆盖 Dockerfile 里 CMD 指令指定的命令

docker run -p 80 --name cmd_test2 -d bga/test:v1 bash

RUN 指令指定的命令是在镜像构建过程中执行的

RUN (shell 模式)

/bin/sh -c command

RUN echo hello

RUN ["EXECUTABLE","param1","param2"] (exec 模式)

RUN ["/bin/bash","-c","echo hello"]

CMD 指令指定的命令是在容器运行时运行的,用来指定容器运行的默认行为,需要注意的是,Dockerfile 中可以有多条 CMD 命令,但只是最后一条有效。如果使用 docker run 命令启动容器时指定了容器运行时的命令,那么 CMD 指令指定的命令会被覆盖不会执行

CMD (shell 模式)

/bin/sh -c command

CMD echo hello

CMD ["EXECUTABLE","param1","param2"] (exec 模式)

CMD ["/bin/bash","-c","echo hello"]

CMD ["param1","param2"] (作为 ENTRYPOINT 指令的默认参数)

ENTRYPOINT 指令与 CMD 指令相似,ENTRYPOINT 指令指定的命令不会被 docker run 启动容器时指定了容器运行时的命令覆盖

它也可用户指定容器启动时要执行的命令,但如果 Dockerfile 中也有 CMD 指令,CMD 中的参数会被附加到 ENTRYPOINT 指令的后面。 如果这时 docker run 命令带了参数,这个参数会覆盖掉 CMD 指令的参数,并也会附加到 ENTRYPOINT 指令的后面

ENTRYPOINT command param1 param2 (shell 模式)

ENTRYPOINT ["executable","param1","param2"] (exec 模式)

使用 ENTRYPOINT 指令代替上面的 CMD 指令

FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
# 在容器启动时运行 nginx,并且以前台的模式运行
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

使用 ENTRYPOINT 来指定命令,用 CMD 来指定命令默认的参数

FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

docker run -p 80 --name cmd_test5 -d bga/test:v3 docker run -p 80 --name cmd_test6 -d bga/test:v3 -g "daemon off;"

可以使用 docker run --entrypoint 覆盖 ENTRYPOINT 指令

docker run -p 80 --name test_entrypoint1 -d --entrypoint=echo bga/test:v3 hello
docker run -p 80 --name test_entrypoint2 --entrypoint=echo bga/test:v3 hello

ADD 和 COPY 指令都是将文件或目录复制到使用 Dockerfile 构建的镜像中。来源可以是本地地址,也可以是远程的 url,如果是本地地址,必须是构建目录中的相对地址,Docker 并不推荐使用远程 url,建议使用 curl 或 wget 来获取文件,目标路径需要指定镜像中的绝对路径

ADD <src>...<dest>
ADD ["<src>"..."<dest>"] (适用于文件路径中有空格的情况)

COPY <src>...<dest>
COPY ["<src>"..."<dest>"] (适用于文件路径中有空格的情况)

ADD vs COPY

ADD 包含类似 tar 的解压功能,如果单纯复制文件,Docker 推荐使用 COPY

测试 COPY 命令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test copy</title>
</head>
<body>
    <h1>TEST COPY</H1>
</body>
</html>
FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
# 在容器启动时运行 nginx,并且以前台的模式运行
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
bingoogolapple commented 7 years ago

ONBUILD 指令

ONBUILD 指令可以为镜像添加触发器。其参数是任意一个 Dockerfile 指令。

当我们在一个 Dockerfile 文件中加上 ONBUILD 指令,该指令对利用该 Dockerfile 构建镜像(比如为A镜像)不会产生实质性影响。

但是当我们编写一个新的 Dockerfile 文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的 Dockerfile 文件中的 ONBUILD 指令就生效了,在构建B镜像的过程中,首先会执行 ONBUILD 指令指定的指令,然后才会执行其它指令。

需要注意的是,如果是再利用B镜像构造新的镜像时,那个 ONBUILD 指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。其实想想是合理的,因为在构建子镜像中已经执行了,如果孙子镜像构建还要执行,相当于重复执行,这就有问题了。

利用 ONBUILD 指令,实际上就是相当于创建一个模板镜像,后续可以根据该模板镜像创建特定的子镜像,需要在子镜像构建过程中执行的一些通用操作就可以在模板镜像对应的 Dockerfile 文件中用 ONBUILD 指令指定。 从而减少 Dockerfile 文件的重复内容编写。

bingoogolapple commented 7 years ago

USER 指令

USER 指令用于指定容器执行程序的用户身份,默认是 root 用户。

在 docker run 中可以通过 -u 选项来覆盖 USER 指令的设置。

docker run -i -t -u mysql newmysqldb /bin/bash

显示的shell提示符是:

mysql@57cd57edba38:/$

注意:docker 容器中的 root 用户密码是随机分配的。

bingoogolapple commented 7 years ago

ENV 指令用来在镜像构建过程中设置环境变量

FROM ubuntu
MAINTAINER hello
ENV MYDIR /mydir
RUN mkdir $MYDIR
RUN echo hello world > $MYDIR/test.txt

假设用上面的 Dockerfile 构建了一个叫 myimage 的镜像。 运行 docker run -i -t myimage /bin/bash

我们发现新建的容器中有了 /mydir 目录,并有了 /mydir/test.txt 文件,文件内容为 hello world

1、通过 ENV 定义的环境变量,可以被后面的所有指令中使用,如上面的例子 2、不能被 CMD 指令使用,也不能被 docker run 的命令参数引用。这个需要注意 3、通过 ENV 定义的环境变量,会永久的保存到该镜像创建的任何容器中。这样除了不能在上面说的启动命令中使用外,可以在后续容器的操作中使用。 4、可以在 docker run 命令中通过 -e 标记来传递环境变量,这样容器运行时就可以使用该变量。如:

docker run -i -t -e "TEST=hello" ubuntu /bin/bash

bingoogolapple commented 7 years ago

WORKDIR 指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。相当于设置容器的工作目录了

FROM ubuntu
MAINTAINER hello
RUN mkdir /mydir
RUN echo hello world > /mydir/test.txt
WORKDIR /mydir
CMD ["more" ,"test.txt"]

假设根据该 Dockerfile 构建的镜像名为 myimage

1、运行 docker run myimage 输出 hello world

2、运行 docker run myimage more test.txt 和上面输出一致

可以看出,more 的参数是 test.txt,但没有指定路径,却能成功,说明当前路径就是上面 WORKDIR 指令设置的。

如果我们在上面的 Dockerfile 中把 WORKDIR 指令去掉,创建的容器运行会报文件不存在错误。

3、可以在 docker run 命令中用 -w 参数覆盖掉 WORKDIR 指令的设置,如:

执行 docker run -w / myimage

上面的 -w 参数将容器的工作目录设置成了根目录,而根目录下没有 test.txt 文件。

所以结果显示:test.txt: No such file or directory

bingoogolapple commented 7 years ago

查看某个镜像构建过程

docker history bga/test:v1

Dockerfile 在构建的过程中默认会使用缓存,每一步构建都会产生中间层镜像,我们也可以基于中间层镜像来运行一个容器并与调试,如果不想使用缓存需加上 --no-cache 参数

docker build --no-cache --tag bga/test:v1 .

或者在 Dockerfile 中指定环境变量 ENV REFRESH_DATE 2015-04-01 来标识缓存刷新的时间,修改了这个时间后就会带来后面命令的缓存刷新

FROM ubuntu:14.04
MAINTAINER bingoogolapple "bingoogolapple@gmail.com"
ENV REFRESH_DATE 2017-01-18
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]