本文最后更新于:星期二, 六月 16日 2020, 2:35 下午
Docker是个好东西,希望大家都能会
0x00 前言
最近由于队伍要招新,需要准备一些练习题放到平台上,队里大哥都跟我说搞web题放自己公网服务器上最好还是整个Docker,防止被什么意料之外的人整个梭穿。以前都没有整过,还是得好好学习一下。
学习第一步肯定是得找找相关资料,这里找到一个Wiki,内容蛮充分的,整挺好
https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md
怎么说,Docker其实就是一个容器,类似于虚拟机,你可以在里面运行一个小型的Linux系统,它的各种功能没有什么影响,但是是一个沙箱,与外部完全隔离。
这种东西比较适合拿来出题,因为一般一个服务器上要放很多道题目,这样可以防止一道题被打穿导致其他的题目都被影响。
0x01 安装
安装还是按官方文档来,安装手册给的蛮全,我这里用的是ubuntu16.04
- 首先还是升级一下apt,保证它是最新的,国内可以把apt源换一下,阿里云亲测还是丝滑一些
$ cd /etc/apt/
$ cp sources.list sources.list.bak #备份
$ sudo vim sources.list
然后把下面的阿里云源粘贴到sources.list里去
#deb包
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
##测试版源
deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse
# 源码
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
##测试版源
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse
# Canonical 合作伙伴和附加
最后
$ apt-get update
$ apt-get upgrade
- 然后我们就可以安装Docker了,先安装Docker需要的依赖环境,首先要让apt可以通过HTTPS来使用仓库
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
- 添加Docker的offcial GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 添加Docker repository
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
- 安装Docker Engine(Community)
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
- 然后就可以选择想要安装的版本了
$ apt-cache madison docker-ce #列出Docker版本
$ sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
也可以直接选择安装最新版
$ sudo apt-get install docker-ce
- 最后查看docker版本
$ docker -v
0x02 拉取镜像
由于从DockerHub上拉取镜像特别慢,所以我们要配置一下国内的镜像源,这样会快很多
$ vim /etc/docker/daemon.json
在里面写入以下内容
{
"registry-mirrors": [
"https://afkemp44.mirror.aliyuncs.com",
"https://dockerhub.azk8s.cn",
"https://reg-mirror.qiniu.com"
]
}
之后重启服务
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
因为我想给服务器搭一个lamp的环境,所以我准备拉一个ubuntu16.04的镜像下来
$ docker pull ubuntu:16.04
这样便成功拉取了一个镜像,如果想要搜索一些镜像,可以使用如下命令
$ docker search [关键词]
0x02 常用操作
拉取完镜像之后,就要将它安装在本机上并让他运行:
docker run --name 容器名 -it -d -p 主机端口:容器端口 -v 主机目录:容器目录:ro 镜像TD或镜像名:TAG
# --name 指定容器名,可自定义,不指定自动命名
# -i 以交互模式运行容器
# -t 分配一个伪终端,即命令行,通常组合来使用
# -p 指定映射端口,将主机端口映射到容器内的端口
# -d 后台运行容器
# -v 指定挂载主机目录到容器目录,默认为rw读写模式,ro表示只读
查看正在运行的容器
docker ps -a -q
# -a 查看所有容器(运行中、未运行)
# -q 只查看容器的ID
启动和停止容器
docker start 容器ID或容器名 # 启动容器
docker stop 容器ID或容器名 #停止容器
删除容器
docker rm -f 容器ID或容器名
# -f 表示强制删除
进入正在运行的容器
docker exec -it 容器ID或者容器名 /bin/bash
# 进入正在运行的容器并且开启交互模式终端
# /bin/bash是固有写法,作用是因为docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动bash。
# 也可以用docker exec在运行中的容器执行命令
拷贝文件
docker cp 主机文件路径 容器ID或容器名:容器路径 # 主机中文件拷贝到容器中
docker cp 容器ID或容器名:容器路径 主机文件路径 # 容器中文件拷贝到主机中
导出容器
docker export $container_id > 容器快照名
导入容器
# docker import命令可以导入容器
cat 容器快照名 | docker import - ctf:1amp5.6 # 导入容器作为镜像
列出镜像
docker images
docker image ls [关键词] # 列出已有镜像中与关键词相关的镜像
镜像保存/载入
docker load
docker save
#将一个镜像导出为文件,再使用docker load命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比docker export命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
将容器直接保存为镜像
docker commit \
--author [作者名] \
--message [备注] \
webserver \ # 容器名
nginx:v2 # 仓库:tag
删除镜像
docker rmi [仓库:tag] # 注意如果有容器基于这个镜像,需要先删除容器才能删除镜像
容器与本机的文件传输
docker cp <path> <containerid>:<path> # 从本机复制文件到容器
docker cp flag e4c6:/ # 从本机复制到容器根目录
docker cp <containerid>:<path> <path> # 从容器复制文件到本机
0x03 使用Dockerfile
使用Dockerfile构建镜像
对于Docker的应用来说,Dockerfile还是一个比较重要且实用的东西了,他可以很方便的共享镜像(主要是网上师傅们的环境都是做成Dockerfile的,不会搞有点难顶)
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
使用Dockerfile相对来说比较简单,只需要用到一条命令:docker build
docker build
有许多种用法:
docker build -t [仓库/tag] . # 这一命令将当前目录下名为Dockerfile的文件build,并以 . 作为上下文路径
关于上下文(Context)可以参考Wiki里的这一部分
docker build -f [Dockerfile路径] -t [仓库:tag] .
# -f用于指定Dockerfile的路径,默认为当前目录下的Dockerfile
使用Git repo进行构建:
docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
#这行命令指定了构建所需的 Git repo,并且指定默认的 master 分支,构建目录为 /11.1/,然后 Docker 就会自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建。
使用给定的tar压缩包构建:
docker build http://server/context.tar.gz
# 如果所给出的 URL 不是个 Git repo,而是个 tar 压缩包,那么 Docker 引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。
从标准输入中读取Dockerfile进行构建:
docker build - < Dockerfile
cat Dockerfile | docker build -
# 如果标准输入传入的是文本文件,则将其视为 Dockerfile,并开始构建。这种形式由于直接从标准输入中读取 Dockerfile 的内容,它没有上下文,因此不可以像其他方法那样可以将本地文件 COPY 进镜像之类的事情。
从标准输入中读取上下文压缩包进行构建:
docker build - < context.tar.gz
# 如果发现标准输入的文件格式是 gzip、bzip2 以及 xz 的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建
编写Dockerfile
编写Dockerfile有几个常用的命令,我这里主要也只说说这几个
FROM
FROM
是一定要的,并且一定要放在第一句,它指定了使用哪个镜像作为最基本的容器使用,例如
FROM ubuntu:16.04
如果本地没有这个镜像它就会去服务器上拉取
RUN
RUN
用来执行命令行命令,所以说一个Dockerfile中大部分都是RUN,RUN的格式有两种,一种是shell格式:RUN <command>
,一种是exec格式:RUN ["可执行文件", "参数1", "参数2"]
RUN echo "hello, world!" # 这种是shell格式
RUN ["ls", "-a"] # 这种是exec格式
但是这里有一个误区,并不是每一个RUN只能对应一条命令行命令来执行,这样反而是不符合规范的,这里贴上Wiki给的解释
之前说过,Dockerfile 中每一个指令都会建立一层,
RUN
也不例外。每一个RUN
的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit
这一层的修改,构成新的镜像。而上面的这种写法,创建了 7 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常犯的一个错误。
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。
所以Dockerfile中,RUN
的正确写法应该是类似这样
RUN apt-get update \
&& apt-get upgrade -y \
&& apt install apache2 -y \
&& apt install php7.0-mysql php7.0-curl php7.0-json php7.0-cgi php7.0 libapache2-mod-php7.0 -y
COPY
COPY
命令用于将本机的文件复制到镜像中,这对一些配置文件很有用,这样你就不需要在建立镜像之后再去一个个改了(特别是在搭CTF环境的时候,把php.ini
,httpd.conf
,.htaccess
这种文件复制一份会方便很多)
COPY
命令的格式为:COPY [--chown=<user>:<group>] <源路径>... <目标路径>
,例如
COPY php.ini /etc/php/7.0/cgi # 这时候php.ini的路径即为build命令中指定的上下文路径
源路径中可以使用通配符,比如
COPY *.php /var/www/html/
还可以使用--chown=<user>:<group>
来改变文件所属的用户和所属组
COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
使用Docker-compose
Docker Compose是个好东西,有时候需要搭建多个容器协同组成的服务的时候,一个docker-compose.yml,搭建起服务来那是又快又省心,官方对Docker Compose的定义是这样的:
Docker Compose
是 Docker 官方编排(Orchestration)项目之一,负责快速的部署分布式应用。
安装
Linux直接从官方Release网站下载即可,或者使用网站上给出的方式下载并安装,比如:
curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
这样也可以安装docker-compose,安装完毕后,运行
docker-compose --version
有回显即安装成功
常用命令
-f, --file FILE
指定使用的 Compose 模板文件,默认为docker-compose.yml
,可以多次指定。-p, --project-name NAME
指定项目名称,默认将使用所在目录名称作为项目名。--x-networking
使用 Docker 的可拔插网络后端特性--x-network-driver DRIVER
指定网络后端的驱动,默认为bridge
--verbose
输出更多调试信息。-v, --version
打印版本并退出。
命令使用说明
build
格式为 docker-compose build [options] [SERVICE...]
。
构建(重新构建)项目中的服务容器。
服务容器一旦构建后,将会带上一个标记名,例如对于 web 项目中的一个 db 容器,可能是 web_db。
可以随时在项目目录下运行 docker-compose build
来重新构建服务。
选项包括:
--force-rm
删除构建过程中的临时容器。--no-cache
构建镜像过程中不使用 cache(这将加长构建过程)。--pull
始终尝试通过 pull 来获取更新版本的镜像。
config
验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因。
down
此命令将会停止 up
命令所启动的容器,并移除网络
exec
进入指定的容器。
help
获得一个命令的帮助。
images
列出 Compose 文件中包含的镜像。
kill
格式为 docker-compose kill [options] [SERVICE...]
。
通过发送 SIGKILL
信号来强制停止服务容器。
支持通过 -s
参数来指定发送的信号,例如通过如下指令发送 SIGINT
信号。
$ docker-compose kill -s SIGINT
logs
格式为 docker-compose logs [options] [SERVICE...]
。
查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。可以通过 --no-color
来关闭颜色。
该命令在调试问题的时候十分有用。
pause
格式为 docker-compose pause [SERVICE...]
。
暂停一个服务容器。
port
格式为 docker-compose port [options] SERVICE PRIVATE_PORT
。
打印某个容器端口所映射的公共端口。
选项:
--protocol=proto
指定端口协议,tcp(默认值)或者 udp。--index=index
如果同一服务存在多个容器,指定命令对象容器的序号(默认为 1)。
ps
格式为 docker-compose ps [options] [SERVICE...]
。
列出项目中目前的所有容器。
选项:
-q
只打印容器的 ID 信息。
pull
格式为 docker-compose pull [options] [SERVICE...]
。
拉取服务依赖的镜像。
选项:
--ignore-pull-failures
忽略拉取镜像过程中的错误。
push
推送服务依赖的镜像到 Docker 镜像仓库。
restart
格式为 docker-compose restart [options] [SERVICE...]
。
重启项目中的服务。
选项:
-t, --timeout TIMEOUT
指定重启前停止容器的超时(默认为 10 秒)。
rm
格式为 docker-compose rm [options] [SERVICE...]
。
删除所有(停止状态的)服务容器。推荐先执行 docker-compose stop
命令来停止容器。
选项:
-f, --force
强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项。-v
删除容器所挂载的数据卷。
run
格式为 docker-compose run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
。
在指定服务上执行一个命令。
例如:
$ docker-compose run ubuntu ping docker.com
将会启动一个 ubuntu 服务容器,并执行 ping docker.com
命令。
默认情况下,如果存在关联,则所有关联的服务将会自动被启动,除非这些服务已经在运行中。
该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照配置自动创建。
两个不同点:
- 给定命令将会覆盖原有的自动运行命令;
- 不会自动创建端口,以避免冲突。
如果不希望自动启动关联的容器,可以使用 --no-deps
选项,例如
$ docker-compose run --no-deps web python manage.py shell
将不会启动 web 容器所关联的其它容器。
选项:
-d
后台运行容器。--name NAME
为容器指定一个名字。--entrypoint CMD
覆盖默认的容器启动指令。-e KEY=VAL
设置环境变量值,可多次使用选项来设置多个环境变量。-u, --user=""
指定运行容器的用户名或者 uid。--no-deps
不自动启动关联的服务容器。--rm
运行命令后自动删除容器,d
模式下将忽略。-p, --publish=[]
映射容器端口到本地主机。--service-ports
配置服务端口并映射到本地主机。-T
不分配伪 tty,意味着依赖 tty 的指令将无法运行。
scale
格式为 docker-compose scale [options] [SERVICE=NUM...]
。
设置指定服务运行的容器个数。
通过 service=num
的参数来设置数量。例如:
$ docker-compose scale web=3 db=2
将启动 3 个容器运行 web 服务,2 个容器运行 db 服务。
一般的,当指定数目多于该服务当前实际运行容器,将新创建并启动容器;反之,将停止容器。
选项:
-t, --timeout TIMEOUT
停止容器时候的超时(默认为 10 秒)。
start
格式为 docker-compose start [SERVICE...]
。
启动已经存在的服务容器。
stop
格式为 docker-compose stop [options] [SERVICE...]
。
停止已经处于运行状态的容器,但不删除它。通过 docker-compose start
可以再次启动这些容器。
选项:
-t, --timeout TIMEOUT
停止容器时候的超时(默认为 10 秒)。
top
查看各个服务容器内运行的进程。
unpause
格式为 docker-compose unpause [SERVICE...]
。
恢复处于暂停状态中的服务。
up
格式为 docker-compose up [options] [SERVICE...]
。
该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
链接的服务都将会被自动启动,除非已经处于运行状态。
可以说,大部分时候都可以直接通过该命令来启动一个项目。
默认情况,docker-compose up
启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。
当通过 Ctrl-C
停止命令时,所有容器将会停止。
如果使用 docker-compose up -d
,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。
默认情况,如果服务容器已经存在,docker-compose up
将会尝试停止容器,然后重新创建(保持使用 volumes-from
挂载的卷),以保证新启动的服务匹配 docker-compose.yml
文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 docker-compose up --no-recreate
。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 docker-compose up --no-deps -d
来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。
选项:
-d
在后台运行服务容器。--no-color
不使用颜色来区分不同的服务的控制台输出。--no-deps
不启动服务所链接的容器。--force-recreate
强制重新创建容器,不能与--no-recreate
同时使用。--no-recreate
如果容器已经存在了,则不重新创建,不能与--force-recreate
同时使用。--no-build
不自动构建缺失的服务镜像。-t, --timeout TIMEOUT
停止容器时候的超时(默认为 10 秒)。
version
格式为 docker-compose version
。
打印版本信息。
0x04 Windows10下使用Docker
官网下载Docker,注意要求Window是professional,即专业版。
下载完之后直接安装,Docker的GUI上没有选择安装路径的选项,只能默认安装在C盘,安装完毕之后重启电脑就可以使用Docker了。Docker For Windows也可以在命令行操作,操作方式基本上是一致的。
使用阿里云镜像加速
Docker默认镜像源在国外,拉取比较慢,可以使用阿里云镜像加速。登录阿里云后,搜索“容器镜像服务”,就可以找到对应的服务支持,点击进入后在“镜像加速器”一栏可以看到自己专属的加速地址。
右键点击右下角docker图标 -> setting -> Docker Engine 中在registry-mirrors
中添加镜像源即可
修改镜像存储位置
因为C盘实在空间不多,所以要修改一下 docker pull 镜像的存储位置,否则C盘顶不住
右键点击右下角docker图标 -> setting -> Resources,在右边页面找到 Disk image location,直接修改位置即可
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!