容器管理工具docker
的出现使开发及运行环境的配置变得更加便利,服务器运维更高效,也成为了后端工程师必须要掌握的效率工具,我们在这里总结一下它的具体使用,关于Linux
下安装docker
相关请看前面一篇:CentOS7安装Docker配置服务端和容器自启动,这里我们将详细介绍docker
的使用,dockerfile
的编写规则和实例,docker-compose
工具的使用和实例,基本上想学会docker
,看这一篇就够了。
Docker基本操作
镜像操作
配置阿里云镜像加速器
为了提高官方镜像拉取速度,我们使用阿里云提供的镜像加速器。
进入容器镜像服务
=> 镜像加速器
,获取自己的加速器地址,替换到下面,运行下面的命令即可。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://*****.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
拉取镜像
比如我们要拉取php
官方镜像,先到hub.docker.com上找到我们想要的
php镜像版本(tags),可以看到,这里有非常多的满足不同需求的版本镜像,我们选
7.1-fpm`,我们的拉取命令就是:
docker pull php:7.1-fpm
不指定tag
从hub
拉取镜像可能会报错,比如:
[root@localhost docker]# docker pull opensips/opensips
Using default tag: latest
Error response from daemon: manifest for opensips/opensips:latest not found
这里是因为pull
默认使用latest
作为镜像tag
,但这个镜像下没有这个未指定这个tag
,所以我们需要手动指定一个存在的tag
拉取。
[root@localhost docker]# docker pull opensips/opensips:2.4
拉取的镜像并不总能直接满足需求,大部分时候我们需要创建自定义镜像,看下面的Dockerfile的使用
部分。
提交镜像
第一步:在https://hub.docker.com/
注册账户并创建仓库;
第二步: 为镜像设置tag
;
比如我要把本地的php71镜像提交到仓库hsu1943/php71:latest
:
docker tag php:7.1 hsu1943/php71:latest
第三步:推送镜像:
docker push hsu1943/php71:latest
容器操作
查看所有容器(包括已停止的)
[root@localhost /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03861a98f878 php:7.1 "docker-php-entrypoi…" 11 days ago Up 33 minutes 0.0.0.0:9000->9000/tcp php71
d3e84fdcd630 nginx:1.14 "nginx -g 'daemon of…" 12 days ago Up 33 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->433/tcp nginx114
0d47cf1170a8 redis:4.0 "docker-entrypoint.s…" 12 days ago Up 33 minutes 0.0.0.0:6379->6379/tcp redis4
076c3f7b2d07 mysql:5.7 "docker-entrypoint.s…" 12 days ago Up 33 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql57
24ecc15d6bda opensips/opensips:2.4 "/run.sh" 3 weeks ago Exited (137) 3 weeks ago opensips
重新启动容器,以下的ID
指的是上面的CONTAINER ID
或者是NAMES
docker restart ID
关闭容器
docker stop ID
强制关闭容器
docker kill ID
删除容器
docker rm ID
查看容器日志
docker logs ID
进入容器并打开终端
docker exec -it ID /bin/bash
查询容器ip地址
docker inspect --format '{{ .NetworkSettings.IPAddress }}' ID
容器中vi
,ipconfig
,ping
命令报错:
command not found
,由于一般镜像未安装这些工具,需要我们安装,当然也可以在自己的镜像Dockfile
中加入。
apt-get update
#vim
apt-get install vim
#ipconfig
apt install net-tools
#ping
apt install iputils-ping
设置容器网络:
使用docker network进行网络相关配置
# 新建网络
[root@localhost /]# docker network create --subnet=172.18.0.0/16 mynetwork
c387a6bdaf315fb156bfddea2edbe772bfa2981e55ee5f23bdbf5aa38a669903
# 查看已有网络
[root@localhost /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
11a662a47a82 bridge bridge local
1cde9f1dc93e host host local
c387a6bdaf31 mynetwork bridge local
0d42b5bfe5e1 none null local
# 查看网络连接情况
[root@localhost /]# docker network inspect mynetwork
# 让容器连接到指定网络指定ip
[root@localhost /]# docker network connect --ip 172.18.0.8 --alias mysql_test mynetwork containerID
# 断开容器网络连接
[root@localhost /]# docker network disconnet mynetwork containerID
# 移除网络,需要该网络中的容器全部断开连接才可以
[root@localhost /]# docker network rm mynetwork
运行容器:
使用docker run
直接来运行一个基于官方镜像mysql:5.7
的容器,根据参数说明,我们就知道如何启动一个容器了。
docker run -d -p 3306:3306 --privileged=true
-v /home/docker/mysql/conf/my.cnf:/etc/mysql/my.cnf
-v /home/docker/mysql/data:/var/lib/mysql
-v /home/docker/mysql/log:/var/log/mysql
--restart=always
--network mynetwork --network-alias mysql
-e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
参数说明:
-d 后台运行
-p 开放端口 格式|主机端口:容器端口
--privileged 提供权限
-v 文件挂载
--restart=always 保持在线
--network mynetwork 使用自定义网络mynetwork
--network-alias mysql 网络别名mysql
-e MYSQL_ROOT_PASSWORD=123456 配置环境变量
--name mysql mysql:5.7 容器名称
备份mysql
容器数据库:
docker exec mysql sh -c 'exec mysqldump --all-databases -uroot -p"123456"' > /some/path/on/your/host/all-databases.sql
从临时容器中获取配置文件
在容器构建过程中需要配置文件挂载,手上没有现成的配置文件?先跑一个临时容器,把默认的配置文件拷贝出来,然后根据自己的情况编辑好配置文件,挂载到使用的容器中去,就可以大道快速部署的目的了。
$ docker run --name tmp-nginx-container -d nginx
$ docker cp tmp-nginx-container:/etc/nginx/nginx.conf /host/path/nginx.conf
$ docker rm -f tmp-nginx-container
# 这里使用了cp命令,在主机和容器之间拷贝文件
Dockerfile的使用
镜像库里的镜像并不能满足所有人的需求,需要根据不同的项目需要来制作自己的镜像,Dockerfile
就很方便的是我们可以以某个镜像为基础(基础镜像),制作一个完全满足自己需求的自定义镜像了供项目需要。具体Dockerfile
的使用技巧,可以参考这里:Dockerfile reference,这里大概总结一下常用操作和基本格式。
在这之前,先了解一下创建镜像。
docker build命令
# build命令默认上下文是当前目录
docker build
# 指定生成镜像的名称以及tag,可以多次指定以生成多个
docker build -t shykes/myapp:1.0.2
docker build
的工作原理(上下文)解析,Docker
在运行时分为 Docker daemon
(服务端守护进程)和客户端工具。Docker daemon
提供了一组REST API
,被称为DockerRemote API
,而如docker
命令这样的客户端工具,则是通过这组API
与 Docker daemon
交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种docker
功能,但实际上,一切都是使用的远程调用形式在服务端(Docker daemon
)完成。也因为这种C/S
设计,让我们操作远程服务器的Docker daemon
变得轻而易举。
当我们进行镜像构建的时候,并非所有定制都会通过RUN
指令完成,经常会需要将一些本地文件复制进镜像,比如通过COPY
指令、ADD
指令等。而docker build
命令构建镜像,其实并非在本地构建,而是在服务端,也就是Docker daemon
中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径, docker build
命令得知这个路径后,会将路径下的所有内容打包,然后上传给Docker daemon
。这样Docker daemon
收到这个上下文包后,展开就会获得构建镜像所需的一切文件。
# 会将上下文(context)发送给Docker daemon
docker build .
Sending build context to Docker daemon 6.51 MB
...
docker build
命令的上下文还可以是git
仓库,压缩文件甚至是文本文件。更多的关于docker build
命令相关看这里:docker build。
千万不要在根目录之类的目录作为上下文,一般使用一个空目录,把
Dockerfile
和需要的文件放在该目录下进行创建。
在Dockerfile
中使用一些操作(比如COPY
)将上下文目录中的文件添加到镜像中,可以使用.dockerignore
文件指定要忽略的目录或者文件,不知道如何编写一个.dockerignore
文件?传送门。
默认会使用上下文目录下的Dockerfile
,也可以在命令中指定它:
$ docker build -f /path/to/a/Dockerfile .
在执行Dockerfile
前,Docker daemon
会一条条去校验其中的指令,如果有错误将会提示错误并停止执行。
Docker daemon
会一条一条的执行指令,每一条产生一个新的层
,每一层是独立存在,所以在上一个指令中的cd /tmp
对后面的指令没有影响,为了提高执行效率,应该尽量将同一类的指令放到一起执行,减少层
,在执行过程中,默认会使用缓存,也就是如果之前有执行过,生成的层镜像
和现在需要的是一样的,那就直接用缓存了。
Dockerfile格式
以#
开头后面视为注释(除解析器指令);Dockerfile
指令不区分大小写,不过一般约定指令使用大写,与参数区分;
FROM:必须使用FROM
指令开头,来指定基础镜像;
- 镜像可以是任意有效的镜像 – 这个很容易从公共仓库拉取一个镜像。
- FROM必须是Dockerfile中的首个非注释指令。
- FROM可以在单个Dockerfile中出现多次,这样可以创建多个镜像。只需记下在每个新的FROM命令之前由提交输出的最后一个图像ID。
- tag或digest值是可选的。如果都不指定,那么默认是latest。如果找不到tag的值将返回错误。
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
MAINTAINER:设置生成这个镜像的作者。
MAINTAINER hsu1943 "88888888@qq.com"
ENV:声明环境变量,可以在其他指令中使用;
- 在
Dockerfile
引用环境变量可以使用$variable_name
或${variable_name}
。它们是等同的,其中大括号的变量是用在没有空格的变量名中的,如${foo}_bar
。 ${variable_name}
变量也支持一些标准的bash
修饰符,如:${variable:-word}
表示如果variable
设置了,那么结果就是设置的值。否则设置值为word
。${variable:+word}
表示如果variable
设置了,那么结果是word
值,否则为空值
word
可以是任意的字符,包括额外的环境变量。- 转义符可以添加在变量前面:
$foo
或者${foo}
,例如,会分别转换为$foor
和${foo}
。
FROM busybox
ENV foo /bar
ENV PHP_INI_DIR /usr/local/etc/php
WORKDIR {foo} # WORKDIR /bar
ADD .foo # ADD . /bar
COPY foo /quux # COPYfoo /quux
COPY:将上下文目录中的文件复制到docker镜像中
这个命令很直观,也很可靠,在这里大家可能会想到ADD
命令,这个命令除了复制文件以外还会做更多(复制远程文件,可以自动解压缩),但我们还是建议直接用COPY
就够了,降低复杂度,提高成功率。
对于目录而言,COPY
只复制目录中的内容而不包含目录自身,所以当你需要复制包含目录的话,应该指定目标路径目录。
COPY docker-php-source /usr/local/bin/
ENTRYPOINT和CMD:设置容器启动时要执行的命令
这两个命令功能上是很相似的,所以也很容易混淆,基本原则:
- Dockerfile中至少有一个(
ENTRYPOINT
或者CMD
),不然回会报错; - 多个
ENTRYPOINT
或多个CMD
只会执行最后一条; - 如果
ENTRYPOINT
使用了shell
模式,CMD
指令会被忽略; - 如果
ENTRYPOINT
使用了exec
模式,CMD
指定的内容被追加为ENTRYPOINT
指定命令的参数; - 如果
ENTRYPOINT
使用了exec
模式,CMD
也应该使用exec
模式。
对于 CMD
和 ENTRYPOINT
的设计而言,多数情况下它们应该是单独使用的。当然,有一个例外是 CMD
为 ENTRYPOINT
提供默认的可选参数。
如果还是不清楚,看看官方给出的这个图,大概就能理解了:
LABEL:添加关于镜像的一些信息
LABEL version="1.0"
LABEL description="This text illustrates
that label-values can span multiple lines."
LABEL maintainer="SvenDowideit@home.org.au" # 代替MAINTAINER的使用,推荐
因为每一个LABEL都会生成一个新的镜像层,所以建议将LABEL放到一起,可以使用换行达到目的,使用
docker inspect
可以查看镜像的LABEL
s,对于同名(key)的情况,后面的LABEL会覆盖前面的,包括FROM指定的基础镜像中的,多个LABEL合并一起:
LABEL version="1.2.0"
description="about lnmp"
maintainer="SvenDowideit@home.org.au"
other="other value"
EXPOSE:声明容器运行时应该打开的端口
这个指令告诉要运行docker run
这个镜像的运维人员本镜像哪些端口需要映射,在run
的之后可以通过-p
来指定端口映射,或者用-P
随机映射端口,随机映射会将EXPOSE
声明过的端口映射出来。
对于在同一个docker network
中的容器,无需打开端口他们之间就可以通过任何端口来访问彼此。
EXPOSE 9000
USER:指定执行后面RUN,CMD,ENTRYPOINT的用户(组)
使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当不需要管理员权限时,可以通过该命令指定运行用户。一般会在之前创建所需要的用户。
运行容器docker run
时,可以通过-u
参数来覆盖所指定的用户。
WORKDIR:指定工作目录
可以为后面的RUN
, CMD
, ENTRYPOINT
, COPY
以及 ADD
指令指定工作目录,目录中可以解析之前使用ENV
指定的环境变量。
ENV DIRPATH /var
WORKDIR $DIRPATH/www/html
echo pwd
# 会输出 /var/www/html
ARG:构建参数,指定在build时可以传递过来的变量
使用ARG
指定的变量可以在docker build
中通过--build-arg <varname>=<value>
的形式进行传递,这区别于ENV
指定的环境变量,环境变量无法在build
时传递进来。
ARG user1=someuser # 没有传递进来就使用默认值
ARG buildno=1
可以将ARG
和ENV
结合一起使用:
ARG var
ENV var=${var}
ONBUILD:构建子镜像时在FROM之后立即执行在的任务
本镜像并不执行这个指令,而是在子镜像(下一层)中去执行。
# 父容器中Dockerfile内容
FROM busybox
ONBUILD RUN echo "第二次构建(子构建)才执行"
# 构建父镜像
docker build -t father .
# 构建过程中不会打印"第二次构建(子构建)才执行"
创建子容器
# 子容器中Dockerfile内容
FORM father
# 构建子镜像
docker build -t child .
# 构架过程中打印了"第二次构建(子构建)才执行"
VOLUME:指定容器数据挂载点
指定容器中需要挂载到宿主机的挂载点,在宿主机会生成对应的目录(目录名随机)存放数据,需要注意这里跟docker run
中可以指定宿主机目录不同,Dockerfile
中的挂载无法指定宿主机目录,这是为了保证可移植性,规定的目录并不一定在每个宿主机都存在。
VOLUME /var/log/mysql
VOLUME ["/var/log/mysql", "/data2"]
更多关于VOLUME
(共享--volumes-from
)的知识可以参考官方文档。
Dockerfile小技巧:apt使用国内源
# Dockfile开头加一行,使用国内debian源
COPY ./sources.list /etc/apt/sources.list
# 在Dockerfile同目录新建sources.list,内容:
deb http://mirrors.ustc.edu.cn/debian/ stretch main non-free contrib
deb http://mirrors.ustc.edu.cn/debian/ stretch-updates main non-free contrib
deb http://mirrors.ustc.edu.cn/debian/ stretch-backports main non-free contrib
deb-src http://mirrors.ustc.edu.cn/debian/ stretch main non-free contrib
deb-src http://mirrors.ustc.edu.cn/debian/ stretch-updates main non-free contrib
deb-src http://mirrors.ustc.edu.cn/debian/ stretch-backports main non-free contrib
deb http://mirrors.ustc.edu.cn/debian-security/ stretch/updates main non-free contrib
deb-src http://mirrors.ustc.edu.cn/debian-security/ stretch/updates main non-free contrib
# 不同版本的debian修改stretch即可
Dockerfile实例:
FROM php:7.1-fpm
# 使用国内源
ADD sources.list /etc/apt/
# install any custom system requirements
RUN apt-get update && apt-get install -y --no-install-recommends
libfreetype6-dev
libjpeg-dev
libjpeg62-turbo-dev
libmcrypt-dev
libpng-dev
libpq-dev
libicu-dev
libz-dev
libbz2-dev
libmemcached-dev
libxml2-dev
git
&& rm -rf /var/lib/apt/lists/*
# Install various PHP extensions
RUN docker-php-ext-configure bcmath --enable-bcmath
&& docker-php-ext-configure pcntl --enable-pcntl
&& docker-php-ext-configure pdo_mysql --with-pdo-mysql
&& docker-php-ext-configure pdo_pgsql --with-pdo-pgsql
&& docker-php-ext-configure mbstring --enable-mbstring
&& docker-php-ext-configure soap --enable-soap
&& docker-php-ext-install
bcmath
intl
mbstring
mcrypt
mysqli
pcntl
pdo_mysql
pdo_pgsql
soap
sockets
zip
iconv
&& docker-php-ext-configure gd
--enable-gd-native-ttf
--with-jpeg-dir=/usr/lib
--with-freetype-dir=/usr/include/freetype2
&& docker-php-ext-install gd
&& docker-php-ext-install opcache
&& docker-php-ext-enable opcache
&& pecl install xdebug redis
&& docker-php-ext-enable xdebug redis
&& rm -rf /tmp/pear
# AST
RUN git clone https://github.com/nikic/php-ast /usr/src/php/ext/ast/
&& docker-php-ext-configure ast
&& docker-php-ext-install ast
# ICU - intl requirements for Symfony 由于下载巨慢,改成直接COPY压缩包
# Debian is out of date, and Symfony expects the latest - so build from source, unless a better alternative exists(?)
# RUN curl -o /tmp/icu.tar.gz -L http://download.icu-project.org/files/icu4c/63.1/icu4c-63_1-src.tgz
COPY ./icu4c-58_2-src.tgz /tmp/icu.tar.gz
RUN tar -zxf /tmp/icu.tar.gz -C /tmp
&& (
cd /tmp/icu/source
&& ./configure --prefix=/usr/local
&& make
&& make install
)
&& rm -rf /tmp/icu
&& rm /tmp/icu.tar.gz
&& docker-php-ext-configure intl --with-icu-dir=/usr/local
&& docker-php-ext-install intl
# Install the php memcached extension
RUN curl -L -o /tmp/memcached.tar.gz "https://github.com/php-memcached-dev/php-memcached/archive/php7.tar.gz"
&& mkdir -p memcached
&& tar -C memcached -zxvf /tmp/memcached.tar.gz --strip 1
&& (
cd memcached
&& phpize
&& ./configure
&& make -j$(nproc)
&& make install
)
&& rm -r memcached
&& rm /tmp/memcached.tar.gz
&& docker-php-ext-enable memcached
# set timezone
RUN rm /etc/localtime
&& ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#composer
RUN curl -sS https://getcomposer.org/installer | php --
--install-dir=/usr/bin
--filename=composer
这个PHP7.1
的Dockerfile
以官方镜像php:7.1-fpm
为计出镜像,安装了常用的工具及扩展,设置时区及composer
,开包即用,非常方便。
为了更好的理解build
命令的上下文,看一下当前目录结构:
[root@localhost docker]# tree php7
php7
├── Dockerfile
├── icu4c-58_2-src.tgz
└── sources.list
0 directories, 3 files
docker-compose的使用
用于定义和运行多个docker
容器的工具,为运维工作服务器的部署和自动化运维提供了极大的便利,通过一个docker-compose.yml
命令就可以实现多个
安装docker-compose
安装
curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-(uname -s)-(uname -m)" -o /usr/local/bin/docker-compose
添加执行权限
chmod +x /usr/local/bin/docker-compose
关于docker-compose
的使用,以及docker-compose.yml
文件的书写格式,见:
docker-compose官方文档
docker-compose.yml实例
version: '3'
services:
nginx:
image: nginx:1.14
restart: always
# 端口映射
ports:
- "80:80"
- "443:433"
environment:
- TZ=Asia/Shanghai
# 依赖关系
depends_on:
- "php"
# 数据卷
volumes:
# 映射主机./conf.d目录wwwroot目录nginx.conf文件
- PWD/nginx/conf.d:/etc/nginx/conf.d
-PWD/wwwroot:/usr/share/nginx/html
- PWD/nginx/nginx.conf:/etc/nginx/nginx.conf
-PWD/logs/nginx:/var/log/nginx
networks:
- app_net
# 容器名称
container_name: "nginx114"
php:
build: ./php7
restart: always
# image指定build 上下文./php7目录下Dockerfile生成镜像的名称
image: php:7.1
# php-fpm记录日志用
cap_add:
- SYS_PTRACE
ports:
- "9000:9000"
volumes:
# 网站文件目录,配置目录
- PWD/wwwroot:/var/www/html
-PWD/php:/usr/local/etc
networks:
- app_net
container_name: "php71"
mysql:
image: mysql:5.7
restart: always
ports:
- "3306:3306"
# 环境变量
environment:
# mysql密码
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=123456
volumes:
# 挂载数据库文件,配置文件
- PWD/mysql/data:/var/lib/mysql
-PWD/mysql/conf:/etc/mysql
- PWD/logs/mysql:/var/log/mysql
networks:
- app_net
container_name: "mysql57"
redis:
image: redis:4.0
restart: always
# 如果不需要外网访问,使用"127.0.0.1:6379:6379"来限制
ports:
- "6379:6379"
environment:
- TZ=Asia/Shanghai
volumes:
-PWD/redis/data:/data
- $PWD/redis/redis.conf:/etc/redis/redis.conf
networks:
- app_net
container_name: "redis4"
networks:
# 配置docker network
app_net:
driver: bridge
ipam:
config:
# 子网络
- subnet: 178.18.0.0/16
这是一个完整的nginx + php + mysql + redis
多容器的运行环境,结合上面php7.1
的Dockerfile
实例只需要按需要修改挂载目录及配置文件即可运行。
原文链接:https://beltxman.com/2417.html,若无特殊说明本站内容为 行星带 原创,未经同意禁止转载。
感谢博主,文章总结得很全面,受益匪浅
有用就行!
挺不错的博客 留个足迹 博客已经收录在 https://manman.qian.lu/bokeshu
感谢收录