现在在Mac上安装Docker很简单,brew
就可以。
brew cask install docker
貌似没有装cask
的,会自动初始化,直接执行上面的命令即可。支持macOS Sierra 10.12
以上系统。
也可以直接下载Stable或者Edge版本。dmg
文件,直接下载好安装即可。
安装的唯一问题是,可能会在
Updating Homebrew...
这个状态等很久。搬了梯子也不行。找了一下资料,基本都是说更换brew源,而且看了好多页面,都是更换到同一套,我也就直接用了。
cd "$(brew --repo)"
git remote set-url origin https://mirrors.ustc.edu.cn/brew.git
#替换homebrew-core.git
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git
brew update
# 备用地址-1
cd "$(brew --repo)"
git remote set-url origin https://git.coding.net/homebrew/homebrew.git
brew update
# 备用地址-2
cd "$(brew --repo)"
git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/brew.git
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew-core.git
brew update
更新之后,也不算快,估计下载东西比较大。反正等着,自己执行完了。Applications
里面就多了小鲸鱼了。
不知道更换了源对其他安装是否会有影响,如果有问题,就换回默认的:
#重置brew.git
cd "$(brew --repo)"
git remote set-url origin https://github.com/Homebrew/brew.git
#重置homebrew-core.git
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://github.com/Homebrew/homebrew-core.git
上述配置内容,虽然我在很多页面看到都一样,但写的比较认真的是从这里
Mac 解决brew一直卡在Updating Homebrew
引用的。
直接通过yum
安装即可。
$ yum update
$ yum upgrade
$ yum install docker
可能都需要sudo
执行。
安装完了启动docker服务:
$ systemctl start docker
需要root密码进行授权。
然后设置加速镜像
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://gbpursha.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
这样安装下来的是老版本,1.17什么的。新的docker分成了ee和ce,而且版本都是17.xxx,18.xxx这样了。安装新版本:
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
rpm --import https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
yum -y install docker-ce
systemctl enable docker
systemctl restart docker
需要先把老的docker卸载掉。需要remove
掉:
yum remove docker
yum remove docker-common
新版本启动之后,执行docker
命令,说.sock
没权限。把当前用户加入docker组:
sudo gpasswd -a ${USER} docker
升级docker之后,发现有些images没法删除。用root
用户直接删除:
/var/lib/docker/image/overlay2/imagedb/content/sha256
里面的东西。把所有的镜像都删除。重新启动docker服务。但有时候没啥鸟用,直接卸载,删除docker目录,重新安装。
安装指定版本docker
sudo yum -y install --setopt=obsoletes=0 docker-ce-${version}
通过如下命令看可以安装的版本:
yum list docker-ce.x86_64 --showduplicates
默认源pull
镜像会想死。更换国内的加速源
https://gbpursha.mirror.aliyuncs.com
mac os从Preference直接加进去就行。
centos需要在/etc/docker/
中建立daemon.json
文件,加入如下内容:
{
"registry-mirrors": ["https://gbpursha.mirror.aliyuncs.com"]
}
然后重启docker:
sudo systemctl restart docker
mac的docker要用,需要在Applitions里面先运行docker小鲸鱼图标。
先把几个基础命令搞清楚,分清楚镜像、容器,怎么安装和运行。
$ docker run -d -p 80:80 --name webserver nginx
run
命令在指定镜像第一次启动的时候用,相当于执行了两个步骤,将镜像放入容器中(docker create),然后将容器启动,使之变成运行时容器(docker start)。
执行run
命令,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。
上述命令就是查找并安装一个叫nginx
的镜像,并且把nginx端口映射到80上。同时为这个镜像起名叫webserver
。
$ docker start [CONTAINER ID]或者[NAMES]
需要知道容器的id或者名字。
docker pull httpd
或者其他的镜像名字。pull
仅仅是从镜像仓库中把镜像文件拉取到本地,并不会自动创建容器。
$ docker ps -a
知道id或者名字就可以用start
命令来运行。
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
应该说,做镜像文件应该是最难的事情。把自己的东西打包好做成镜像。而且根据这个定义,镜像文件是固定的,如果运行起来需要记录文件等,需要指定到其他的位置(VOLUME
卷)。
Docker 官方维护了一个公共仓库 Docker Hub。可以去注册一个账号,注册了可以发布自己的镜像。
通过docker login
和docker logout
进行登录和退出。
$ docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 5672 [OK]
ansible/centos7-ansible Ansible on Centos7 125 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 114 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 100 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 64
imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 57 [OK]
tutum/centos Simple CentOS docker image with SSH access 44
centos/postgresql-96-centos7 PostgreSQL is an advanced Object-Relational … 39
kinogmt/centos-ssh CentOS with SSH 29 [OK]
centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 26
pivotaldata/centos-gpdb-dev CentOS image for GPDB development. Tag names… 10
nathonfowlie/centos-jre Latest CentOS image with the JRE pre-install… 8 [OK]
drecom/centos-ruby centos ruby 6 [OK]
centos/tools Docker image that has systems administration… 4 [OK]
pivotaldata/centos Base centos, freshened up a little with a Do… 3
darksheer/centos Base Centos Image -- Updated hourly 3 [OK]
会有好多好多。看不出来能干嘛。不如直接google
。
$ docker pull centos
Pulling repository centos
0b443ba03958: Download complete
前面说过,就是把镜像拉到本地了。
import
命令创建镜像。$ docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
参数:
-c :应用docker 指令创建镜像;
-m :提交时的说明文字;
比如:
$ docker import my_ubuntu_v3.tar runoob/ubuntu:v4
$ docker image ls
ls
后面可以带通配符过滤。或者:
$ docker images
$ docker image rm [选项] <镜像1> [<镜像2> ...]
可以是镜像的名字,id都可以。或者指定标签REPOSITORY:TAG
。
可以组合起来按条件删除:
$ docker image rm $(docker image ls -q redis)
ls -q
参数表示只显示只显示镜像ID。
docker rmi -f $(docker images -a -q)
docker容器是进程级的,启动一个容器,也就是启动了一个进程运行镜像文件的内容。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
575213cf1670 nginx "nginx -g 'daemon of…" 8 days ago Up 4 hours 0.0.0.0:80->80/tcp webserver
这样只显示正在运行的容器。
可以加上参数-a
,可以看到已经加载的容器,包括已经运行的和没运行的。
$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
参数太多了,但好像都有用。直接从runoob.com复制过来参数说明:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的高端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
--dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h "mars": 指定容器的hostname;
-e username="ritchie": 设置环境变量;
--env-file=[]: 从指定文件读入环境变量;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--link=[]: 添加链接到另一个容器;
--expose=[]: 开放一个端口或一组端口;
--volume , -v: 绑定一个卷
参数不对,一般是启动不了的。
比如我刚刚pull
了一个叫httpd
的镜像下来,执行:
$ docker run -d -p 8080:80 --name apache httpd
把容器的80端口映射到宿主机的8080端口,并且起了个名字叫apache
,在后台运行。
需要注意的是,再次运行run
则会再次创建一个容器,如果名字相同就会创建失败。如果端口相同,我这里是原来启动的容器被停止,新的容器启动了。
如果用create
命令,则是只创建,但不运行容器了。
$ docker start [OPTIONS] CONTAINER [CONTAINER...]
$ docker stop [OPTIONS] CONTAINER [CONTAINER...]
$ docker restart [OPTIONS] CONTAINER [CONTAINER...]
start
和restart
有两个参数:
-a 将当前的输入/输出连接到容器
-i 将当前的输入连接到容器上
好像输出都到了宿主机的控制台了。
已经创建好的容器,可以用这三个命令来控制启停。
exec
命令: $ docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
参数有:
-d :分离模式: 在后台运行
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端
i
和t
参数往往一起使用。表示打开一个交互终端,比如要进入容器控制台(类似登录到linux服务器的样子)
$ docker exec -it apache bash
就可以执行容器里面的命令,比如ls
等。
run
命令也可以加入-it
参数,但一般作为后台服务来跑,用exec
来控制可能更加多用吧。
除了bash
命令,可以执行容器里面的其他命令。
$ docker logs [OPTIONS] CONTAINER
参数说明:
-f : 跟踪日志输出
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志
$ docker top CONTAINER
docker rm [OPTIONS] CONTAINER [CONTAINER...]
可以是容器的id,或者名字。参数:
-f :通过SIGKILL信号强制删除一个运行中的容器
-l :移除容器间的网络连接,而非容器本身
-v :-v 删除与容器关联的卷
docker rm -vf $(docker ps -a -q)
前面提到镜像文件应该是不可变的。一个正式的服务运行起来,会产生很多动态数据,比如数据库记录,日志等,这些信息是很重要的。容器可能可以随便就删掉,轻松创建,但这些数据不能丢。所以提供了数据卷的概念。在宿主机创建一个卷
,用来保存这些重要的业务数据,就算容器删除了,卷的数据也不会消失。
$ docker volume create my-vol
在本地的/var/lib/docker/volumes
下面创建my-vol/_data
目录,作为卷的实际保存地方。不过有几个问题:
/var/lib/docker/volumes
默认目录,不知道怎么改,如果一定要在这里的话,需要在linux宿主机上专门挂这个目录才行。create
命令对于不同的存储介质有很多参数,docker支持很多存储介质,比如本地磁盘,nfs设置S3,不同的介质需要对应不同的参数,按照docker的说法,这些参数直接传给设备,具体就需要去查了。用--driver
指定驱动程序和用-o
指定参数。在linux下没问题,就有这个目录,直接把需要的内容弄进去就好了。
但跑到mac电脑的/var/lib
下面根本没有docker
目录!docker其实不是直接运行在mac os上,而是在mac os上弄了一个虚拟的linux环境,所以这个/var/lib/docker
目录对应的是linux虚拟环境的目录。
执行如下命令进入到linux虚拟环境中:
$ cd ~/Library/Containers/com.docker.docker/Data/vms/0/
$ screen tty
这样出来的终端界面就能找到对应的目录了。进去看看,里面是空的。不知道怎样把mac的内容拷贝进去。
另外,根据文章指出,这个linux虚拟环境退出,需要按住ctrl然后,按a和k。说其他退出方式,会导致有问题。如果有问题,重启docker。
mac目录问题,从[工具][docker]記錄Volume相關引用过来。
比如我要创建了一个叫apache的httpd容器。我打算把真是的网站放在web卷中。先创造卷:
$ docker volume create web
如果是linux就直接把网站内容拷贝到var/lib/docker/volumes/web/_data
里面,如果是mac就抓瞎。
然后给容器挂载卷。
$ docker run -d -p 8080:80 --name apache -v webapp:/usr/local/apache2/htdocs httpd
-v
参数确定卷名:容器中的的绝对路径
。可以先用exec
进去看看容器里面对应的网站根目录在哪里。如果是linux,拷贝内容进去就好了。如果是mac,换一种方式,直接指定本机目录挂到容器里面:
$ docker run -d -p 8080:80 --name apache -v /Users/web:/usr/local/apache2/htdocs httpd
把网站内容拷贝到/Users/web
目录中就可以。
从 Docker小图标 -> Preferences 进到 File Sharing。可以看到Users
目录是共享的。
$ docker volume rm my-vol
进行删除。
$ docker volume ls
使用inspect
命令检查对象,比如镜像,容器,卷的信息。
$ docker inspect 对象名字
可以可以到信息。
$ docker run -d -e MYSQL_ROOT_PASSWORD=password -p 53306:3306 --privileged=true --name mysql docker.io/mysql
--privileged=true
表示root
在容器内有真正的root
权限。
启动镜像, 第一次启动最少需要指定MYSQL_ROOT_PASSWORD
需要修改使用自己的配置文件,可以通过绑定卷实现。
需要登录到容器中修改权限。
$ docker run --name nginx-test -p 8080:80 -d nginx
需要配置:
映射80端口到需要的端口。
/etc/nginx/conf
目录或者 /etc/nginx/conf/nginx.conf
,nginx配置文件
/usr/share/nginx/html
默认的web根目录
redis
$ docker run -itd --name redis-test -p 6379:6379 redis
可以看出下载一个现成的docker镜像要用起来的话,有几个条件需要知道:
/usr/share/nginx/html
官方提供的镜像一般都有详细的说明,hub.docker.com
上也会提供Dockerfile,这个都可以先看的。剩下的,就是多尝试了,大不了先把镜像跑起来,用exec
进去看看是怎么配置的。
从上面的过程来看,docker进行文件的制作才是最重要的。开发好一个服务端应用之后,怎么制作镜像文件,怎么利用docker合理的部署,需要几个镜像,怎么划分等。
制作镜像文件最重要就是编写Dockerfile。
Dockerfile 分为四个部分:
一个最简单的Dockerfile:
#nginx基础镜像
FROM nginx
#指定工作路径
WORKDIR /usr/share/nginx/html
#将前前路径下的所有文件都COPY到工作路径下
COPY . .
#EXPOSE 命令用来指定对外开放的端口,实际用处不大,可不写
EXPOSE 80
Dcokerfile命令如下:
MAINTAINER xxxxx
。COPY . /app
path
,JAVA_HOME
等。VOLUME ["<路径1>", "<路径2>"...]
。WORKDIR /path/to/work/dir
。RUN pip install -r requirements.txt
EXPOSE 80
ENTRYPOINT ["executable", "param1", "param2"]
:推荐使用的 Exec 形式。ENTRYPOINT command param1 param2
:Shell 形式。CMD ["executable","param1","param2"]
:推荐使用的 exec 形式。CMD ["param1","param2"]
:作为ENTRYPOINT的参数。CMD command param1 param2
:Shell 形式。docker run nginx
感谢Docker系列之四:Dockerfile的使用。从这里参考不少资料。
重点解释几个命令:
RUN
RUN
命令其实就是构建这个镜像的时候,基于基础的镜像操作系统执行的一些列命令,让这个环境变成你所要的。比如,基于centos
系统,安装java安装数据库等。一般默认的操作系统是debain
,使用apt-get
安装软件,如果选择centos
则使用yum
来安装了。
为了打包快,基本上,第一个干的事情,是更改apt
或者yum
的源了。
按照说明,一个RUN
命令,形成一个新的镜像,多个RUN
就是一层一层的做镜像。如果不想多层镜像,就把所有的指令都在一个RUN
里面执行完。命令间用\分割。如:
apt update -y \
&& apt upgrade \
&& apt install mysql-server -y \
&& apt install redis-server -y
ADD和COPY
两个命令都是把外部的资源复制到镜像中。ADD除了支持把主机的文件,还支持远程URL
资源。但ADD不支持认证。一般也不支持用ADD
获取远程资源,可以在RUN
中用wget
获取。
前面提到更新apt-get
的资源,可以:
$ ADD ./sources.list /etc/apt/
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
ENV环境变量
能在构建容器的时候指定的环境变量就在Dockerfile里面指定,毕竟,有些环境变量可能在RUN
的时候就会用到。有些比如前面mysql
的镜像,root
的口令,可以run
的时候指定。
ENTRYPOINT和CMD
这两个指令,在构建镜像的时候不会运行,在run
的时候执行。相当于镜像启动起来的服务。比如,做一个tomcat
的镜像,启动容器的时候自动把tomcat
运行起来。
这两个必须有一个。
两个命令后面都有带[]
和不带中括号的。是所谓的exec
模式(带中括号)和shell
模式(不带中括号)。推荐是exec
模式。区别好像很重要,貌似哪个是1号进程。但我不是很清楚。
CMD作为默认命令,可以被run
的参数覆盖。
对于 CMD 和 ENTRYPOINT 的设计而言,多数情况下它们应该是单独使用的。当然,有一个例外是 CMD 为 ENTRYPOINT 提供默认的可选参数。
说了一大堆,其实,一般情况,就用ENTRYPOINT
好了。别搞这么复杂。另外,不管CMD
还是ENTRYPOINT
都只能一个生效,如果写了多个,最后一个生效。如果需要启动多个服务,就写一个脚本,COPY
进来,执行就好。
然而,需要注意的是,启动脚本里面,直接运行命令,而不要用systemctl
这样启动服务。如果多个服务,前面的都加&
放到后台,最后一个放前台。否则,容器启动完了就退出了。
比如我的一个启动脚本:
#!/bin/bash
mysqld_safe &
redis-server &
sleep 5s
catalina.sh run
我的tomcat如果在mysql没启动完成就起来了会出错,所以让他睡觉5秒钟。
VOLUME
Dcokerfile里面定义了卷,在运行的时候,如果不显示的指定卷,就会自动创建匿名的卷
如果自己做镜像,可能最麻烦的就是RUN
的环节了。可能需要执行很多命令比如:
最好在一个相同的容器里面,每行命令都执行一下,验证通过,同步记录执行的脚本。
最后,构建镜像的命令,在Dcokerfile目录下执行:
$ docker build -t runoob/ubuntu:v1
tar
文件。$ docker save [镜像名] > [文件名]
导入镜像文件
$ docker load < [文件名]
镜像文件是静态的,不会因为你在对应的容器里面做了什么而改变。一开始制作或者下载的镜像文件是什么样,导出的时候还是什么样。
tar
文件。$ docker export [容器id] > [文件名]
$ docker import [文件名]
可以把导入的镜像打标签:
docker tag [镜像id] [镜像名字]:[版本号]
不过,要注意的是,导出来的镜像或者容器快照,都会很大很大。
docker安装好之后,主机会多一个docker0
的网卡。用来跟容器通信的。复杂的机制我们不管他,总之,安装之后就有了。而且,运行容器之后,容器本身也会分配一个ip地址。但这个地址,每次重启容器,都可能会改变。想用这个地址来做容器之间通信,是不靠谱的。
所以,就需要专门创建网络。并且把容器都加入到这个网络里面,就可以通过容器的名字来通信了。
创建网络:
$ docker network create congnet
查看这个网络的信息:
$ docker network inspect congnet
可以看出:
"Scope": "local",
"Driver": "bridge",
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
docker网络有好几种模式,反正桥接模式就是能访问所有的网络。
创建容器,并加入指定网络:
$ docker run -itd -p 80:80 --name mynginx --net congnet nginx
把已经存在的容器加入到网络:
$ docker network connect congnet [容器id]
这样,容器之间就可以互相用容器的名字通信了。
断开网络:
$ docker network disconnect congnet mynginx
到这里,容器都是在一个主机上的。实际情况,很有可能容器在不同的主机上。这就需要单独的东西。我还没验证。根据资料,用overlay
。需要安装consul
。
暂时不搞他。
下载安装docker-compose
$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
即可完成。
docker-compose
使用YAML
文件定义多个镜像以及依赖关系。
太复杂了,直接复制一个过来。
#版本号
version: "2.1"
#指定创建的虚拟网络数量
#作用:通过不同的虚拟网络实现了容器网络之间的隔离,从而在最大程度上去保护后端网络的安全。
#networks:
#mynet:
#driver: bridge
#mynet1:
#重用的代码模板
#模板的定义必须以 x- 开头
x-logging:
#以 & 开头的字符串为模板命名
#以 * 加上模板的名称引用模板
&default-logging
driver: json-file
options:
max-size: "200k"
max-file: "10"
#定义全局挂载卷
volumes:
test_1.thinking.com:
test_2.thinking.com:
#服务
services:
#服务名称
todo:
# 构建镜像
build:
# 指定dockerfile的上下文路径(相对当前docker-compose.yml的位置)
#包含Dockerfile文件的目录路径,或者是git仓库的URL。
#当提供的值是相对路径时,它被解释为相对于当前compose文件的位置。
#该目录也是发送到Docker守护程序构建镜像的上下文。
context: .
#Dockerfile的文件名称
dockerfile: Dockerfile-todo
args:
# 变量
buildno: 1
password: secret
#Dockerfile里面可使用的参数变量
#Dockerfile:
# ARG buildno
# ARG password
# RUN echo "Build number: $buildno"
# RUN script-requiring-password.sh "$password"
#镜像名 : 仓库/标签:版本
image: zhanyang/todo-demo:1.0.0
#依赖(以指定顺序启动)
depends_on:
mysql:
condition: service_healthy
#指定一个自定义容器名称,而不是生成的默认名称。
#由于Docker容器名称必须是唯一的,因此如果指定了自定义名称,则无法将服务扩展到多个容器。
container_name: todo
#卷挂载路径设置。
#可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)
#挂载数据卷的默认权限是读写(rw),可以通过ro指定为只读。
volumes:
# 只需指定一个路径,让引擎创建一个卷
- /var/lib/mysql
#指定绝对路径映射
- /opt/data:/var/lib/mysql
#相对于当前compose文件的相对路径
- ./cache:/tmp/cache
#用户家目录相对路径
- ~/configs:/etc/configs/:ro
#命名卷
- datavolume:/var/lib/mysql
#使用全局挂载卷
- test_1.thinking.com:/test:rw
#指定日志驱动为 json-file,存储日志的最大文件 size 为 200k,最多存储 10 这样大的文件。
#logging支持很多driver,而每一个driver对应的options都不一样
#docker inspect -f {{.HostConfig.LogConfig}} lnmp-nginx
#result:{json-file map[max-file:10 max-size:2000k]}
#docker info |grep 'Logging Driver'
#result:Logging Driver: json-file
#其他:https://docs.docker.com/engine/admin/logging/overview/
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
#指定使用的虚拟网络
networks:
#- mynet
#覆盖容器启动后默认执行的命令。
#该命令也可以是一个类似于dockerfile的列表:command: ["bundle", "exec", "thin", "-p", "3000"]
command: bundle exec thin -p 3000
#may
command: ["/usr/local/nginx/sbin/nginx"]
# 链接到另一个服务中的容器。 请指定服务名称和链接别名(SERVICE:ALIAS),或者仅指定服务名称。
# 实际是通过设置/etc/hosts的域名解析,从而实现容器间的通信。
# 故可以像在应用中使用localhost一样使用服务的别名链接其他容器的服务,前提是多个服务容器在一个网络中可路由联通
# links也可以起到和depends_on相似的功能,即定义服务之间的依赖关系,从而确定服务启动的顺序
links:
- db
- db:database
- redis
#链接到docker-compose.yml 外部的容器,甚至并非 Compose 管理的容器。参数格式跟 links 类似。
external
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
#暴露端口,但不映射到宿主机,只被连接的服务访问。 仅可以指定内部端口为参数
expose:
- "3000"
- "8000"
#暴露端口信息。使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
#v3.2中ports的长格式的语法允许配置不能用短格式表示的附加字段。
ports:
- target: 80 #容器内的端口
published: 8080 #物理主机的端口
protocol: tcp #端口协议(tcp或udp)
mode: host #host 和ingress 两总模式,host用于在每个节点上发布主机端口,ingress 用于被负载平衡的swarm模式端口。
#no是默认的重启策略,在任何情况下都不会重启容器。
restart: "no"
#指定为always时,容器总是重新启动。
restart: always
#如果退出代码指示出现故障错误,则on-failure将重新启动容器。
restart: on-failure
restart: unless-stopped
#pid 将PID模式设置为主机PID模式。
#这就打开了容器与主机操作系统之间的共享PID地址空间。
#使用此标志启动的容器将能够访问和操作裸机的命名空间中的其他容器,反之亦然。
#即打开该选项的容器可以相互通过进程 ID 来访问和操作。
pid: "host"
#配置 DNS 服务器。可以是一个值,也可以是一个列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
#自定义搜索域
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
#覆盖Dockerfile中的entrypoint,用法同Dockerfile中的用法
entrypoint: ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
#添加环境变量。 你可以使用数组或字典两种形式。
#任何布尔值; true,false,yes,no需要用引号括起来,以确保它们不被YML解析器转换为True或False。
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
#【注意】:如果你的服务指定了build选项,那么在构建过程中通过environment定义的环境变量将不会起作用。
#将使用build的args子选项来定义构建时的环境变量。
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRE
#1>将定义的变量编写在文件中,然后在yml文件中进行添加
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
#2>例如:
#old:
db:
image: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: redhat
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
#new:
db:
image: mysql
ports:
- "3306:3306"
env_file: ./mysql_env
#创建env_file文件在当前目录mysql_env
MYSQL_ROOT_PASSWORD=redhat
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress
MYSQL_PASSWORD=wordpress3
#添加hostname映射,类似于docker cli下面的--add-host
extra_hosts:
- "www.hcstart.com:192.168.101.14"
#配置一个检查去测试服务中的容器是否运行正常
#具体: https://docs.docker.com/engine/reference/builder/#healthcheck
#查看healthcheck的状态输出 : docker inspect lnmp-nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
#labels:添加元数据到container中,查看现有容器的labels:
#docker inspect -f {{.Config.Labels}} lnmp-nginx # lnmp-nginx :容器名
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
#在容器中设置内核参数
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
mysql:
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: tododb
MYSQL_USER: user
MYSQL_PASSWORD: pass
build:
context: .
dockerfile: Dockerfile-mysql
image: zhanyang/mysql:5.6
container_name: mysql
#以 * 加上模板的名称引用模板 使用全局自定义模板
logging: *default-logging
#指定使用的虚拟网络
networks:
#- mynet1
参考:docker-compose.yml参数详解(配置文件)。
在 docker-compose.yml
文件目录下执行:
$ docker-compose up -d