0x00前言
上篇博客留的坑还是要填的,正好开始自己的Docker之旅...
0x01 Docker安装
首先允许docker使用HTTPS
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common
加入Docker官方的GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
debian系统
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
在源中加入Docker的源,然后更新系统
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/debian \
$(lsb_release -cs) \
stable"
输入命令sudo apt-get install docker-ce
安装Docker,输入docker-v
显示版本
Docker version 18.09.3, build 774a1f4
0x02 Docker介绍
什么是容器?
一句话来说,容器就是将软件包打包成标准化单元用于开发、交付和部署使用
- 容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
- 容器化软件适用于基于Linux和Windows的应用,在任何环境中都能运行。
- 容器赋予了软件独立性,使其免受外在环境差异(例如,开发和预演环境的差异)的影响。
Docker简介和思想
简介:
- 用户能够自动地执行重复任务,例如搭建和配置开发环境,从而解放了开发人员。
- 用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样
- Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性
- 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间
- 避免公用的服务器,资源会容易受到其他用户的影响
- 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况
思想:
- 集装箱
- 标准化
- 隔离
Docker镜像
Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。
Docker容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。
Docker不为虚拟机,容器中的应用都应该在前台执行,没有后台服务的理念
对于容器而言,启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出
0x03 Docker基本命令
build命令和run命令在RPO浅析中已近说了大部分的命令了,所以就不再概述了
# 列举CLI命令
docker container --help
# 启动一个Docker镜像
docker image ls
docker images
# 查看Docker容器
docker container ls
docker container ls --all
docker container ls -aq
docker ps
# 启动一个容器
docker start <docker-container-ID>
# Docker错误检查
docker logs <container_id>
# 如果启动不了容器可以在路径 /var/lib/docker/overlay 路径下面查找需要修复的docker地址,可以使用find命令查找
# Docker打包镜像
docker commit <container_id> <image_name>:<tag>
# 复制文件进入容器内
docker cp <docker_ID>:<path> <user-path>
#将文件复制进容器内
docker cp <path> <docker_ID>:<path>
# Docker进入容器
docker attach IMAGEID
或者使用命令
docker exec -ti <docker_name> /bin/bash
docker stop container-name #停止正在运行的容器
# 删除一个Docker容器
docker rmi imageID
-f 强制删除
--no-prune 不移除该镜像的过程镜像,默认移除
0x04Dockerfile
使用Dockerfile来定制化容器
容器信息
# 声明容器
FROM ubuntu:17.10
# 作者信息
MAINTAINER christa
# 书写时间
ENV REFRESHED_AT 2019-01-01
# 使用utf-8编码
ENV LANG C.UTF-8
RUN
接受命令作为参数并且用于创建镜像,在当前镜像的的顶层中执行命令并提交结果,新镜像用于下一步的Dockerfile。在shell形式中,可以使用\(反斜杠)将单个RUN指令继续到下一行,一般书写为:
RUN <command> (默认情况下Linux为/bin/sh -c, Windows 为 cmd /S/CWindows中运行)
CMD
主要为一个正在运行的容器提供默认执行命令,如果存在多个指令,那么只有最后一个会被执行,如果在容器运行时指定了命令,则CMD指定的默认内容会被替代。同时支持三种格式:
CMD [“executable”,"param1","param2"] 使用exec方式,推荐使用这一种
CMD command param1 param2 在/bin.sh中执行,提供需要交互的应用
CMD ["param1","param2"] 提供给 ENTRYPOINT的默认参数
例如 CMD ["echo" ,"docker test"]
、CMD ["sh","-c","docker test"]
ENTRYPOINT
命令和CMD一样,区别在于ENTRYPOINT后面携带的参数不会被Docker run覆盖,而CMD会。
COPY
复制文件,将文件复制到容器内,使用本地目录为源目录时,推荐使用COPY
COPY <src> <dest>
ADD
将复制指定的 <src> 到容器中的 <dest>。 其中 <src> 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(自动解压为目录)。
ADD <src> <dest>
ENV
用用于设置环境变量,可以在容器和脚本里面直接使用
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>
EXPOSE
设置暴露出容器内部端口,不是主机的端口
EXPOSE [port]
如果需要将主机端口转换成内部端口则可以使用如下命令,例如EXPOSE 4668
docker run -d -p 127.0.0.1:8080:4668 docker/test
WORKDIR
指定容器工作目录,所执行的命令都是在当前目录下执行的
WORKDIR <path>
VOLUME
为了能够保存(持久化)数据以及共享容器之间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或文件,他可绕过默认的联合文件,而以正常的文件或者目录的形式存在于宿主机上。通常有两种方式来初始化Volume,在运行的时候使用-v
来声明Volume
docker run -it --name container-test -h CONTAINER -v /data ubuntu/bin/bash
上面的命令会将/data
挂载到容器中,并绕过联合文件系统。任何在该镜像/data
路劲的文件将会被复制到Volume,使用docker inspect
命令找到Volume在主机上的存储位置
docker inspect -f {{.Volumes}} container-test
通常设置Volume的权限或者为Volume初始化默认数据或者配置文件。注意:在Dockerfile的Volume指令后的任何东西都不能改变Volume,比如:
FROM debian:wheezy
RUN useradd christa
VOLUME /data
RUN touch /data/x
RUN chown -R christa:christa /data
该Docker file不能按预期那样运行,我们本来希望touch
命令在镜像的文件系统上运行,但是实际上它是在一个临时容器的Volume上运行。如下所示:
FROM debian:wheezy
RUN useradd christa
RUN mkdir /data && touch /data/x
RUN chown -R christa:christa /data
VOLUME /data
Docker可以将镜像中Volume下的文件挂载到Volume下,并设置正确的权限。如果你指定Volume的主机目录将不会出现这种情况。
删除Volume
当使用过docker rm
删除容器的时候任然会有孤立的Volume在占用着空间,Volume只有在如下情况才能被删除
- 该容器是用
docker rm -v
命令来删除的(-v
是必不可少的)docker run
中使用了--rm
参数
Dockerfile的写法为
VOLUME ["/dir_1", "/dir_2" ..]
docker-compose.yml
本次语言主要是使用的是version: '3'
docker-compose.yml文件装门为docker-compose所使用的类似于Dockerfile文件,docker-compose安装可以使用pip安装,命令为pip install docker-compose
结构
主要分为三个部分:service、networks、volumes
services主要用来定义各个容器,networks定义需要用到的networks,volumes定义services使用到的volumes
service
使用当前目录下的Dockerfile进行构建
version: '3'
services:
web:
build :./
假设当前文件夹名为ccweb,则构建出来的镜像名字为ccweb_web,运行出来的容器名:ccweb__web_1,若果docker-compose up的时候,ccweb_web镜像不存在,才会构建。docker-compose build会重新构建镜像,原来的镜像变成
version: '3'
services:
web:
build:
context: ./
dockerfile: owndockerfile
depends_on
指定容容器的依赖,一般是mysql,redis等,links也可以用与服务创建并启动依赖
image
制定运行的容器,有如下格式
image: redis
image: ubuntu:17.10
image: tutum/infuxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
如果定义了build,那么image指定的就是build后的镜像的名字和tag
version: '3'
services:
web:
build: ./
image: web:1.0
volumes
挂载一个目录或者一个已存在的数据卷容器, HOST:CONTAINER 格式定义共享的目录 HOST:CONTAINER:RO 定义容器只读的目录。
volumes:
- ./conf.d:/etc/nginx/conf.d
# nginx.conf对容器来说只读
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks
version: '3'
services:
...
networks:
- fornt-tier
- end-tier
env_file
定义了docker_compose.yml中使用的变量,提高docker-compose.yml的灵活性
env_file: .env
env_file:
- ./tem.env
- ./apps/key.env
env文件中格式 key:value, 例如
RACK_ENV=securey_key
DB_PORT=3306
ports
将容器的80的端口映射到宿主机的8080端口上
ports:
- "8080:80"
- "172.168.0.2:8080:80"
用一个例子来说
version: '3'
services:
nginx:
image: nginx:1-alpine
depends_on:
- web
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80"
web:
build: .
command: bash server.sh
env_file:
- .env
其文件tree结构为
├─picklecode
│ ├─nginx
│ └─web
│ ├─challenge
│ │ ├─migrations
│ │ └─templates
│ │ └─registration
│ └─core
└─thejs
└─web
├─static
└─views
创建一个镜像使用web文件夹的内容,将nginx文件夹的nginx的default.conf文件映射到/etc/nginx/conf.d/defualt.conf
中,并且将端口从宿主机的8083端口映射到容器的80端口,构建一个webapp,用本地的Dockerfile进行创建,同时运行server.sh脚本,使用虚拟文件 .env进行创建
docker-compose.yml文件对配置内容的缩进非常看重,因此编写时需要特别注意
docker-compose
常用命令为
docker-compose up -d 创建并且启动镜像
docker-compose up -d nginx 构建建启动nignx容器
docker-compose exec nginx bash 登录到nginx容器中
docker-compose down 删除所有nginx容器,镜像
docker-compose ps 显示所有容器
docker-compose build 构建镜像 。
docker-compose build --no-cache 不带缓存的构建。
docker-compose events --json nginx 以json的形式输出nginx的docker日志
docker-compose pause <container> 暂停容器
docker-compose unpause <container>恢复容器
docker-compose rm <container> 删除容器(删除前必须关闭容器)
docker-compose stop <container> 停止容器
docker-compose start <container> 启动容器
使用docker-compose或者docker run开启景象之后会有如下的显示:
pi@raspberrypi:~ $ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3086131b6343 nginx:1-alpine "nginx -g 'daemon of…" 25 hours ago Up 25 hours 0.0.0.0:8083->80/tcp christa_nginx_1
e1294b211aac christa_web "bash server.sh" 25 hours ago Up 25 hours 8000/tcp christa_web_1