在Docker里面,镜像和容器是两个概念,镜像类似操作系统的ISO,而容器则是以该ISO为基础生成而来的。
系统相关
boot2docker
默认用户名是docker
,密码是tcuser
。
现在docker for mac
不再依赖virtualbox
等虚拟化软件,但是其采用了虚拟化技术,仍然是有虚拟机的,可以通过这条命令进入虚拟机查看``screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
镜像和容器
1 | docker pull ubuntu:14.04.1 # 拉取官方镜像 |
创建容器
启动参数
1 | --add-host=host:IP # 给hosts添加一行 |
启动命令
1 | docker run命令用于从镜像创建一个容器 |
容器操作
1 | docker start #和docker run后面参数一样,只是它是重启容器,而docker run是创建容器 |
Dockerfile
Dockerfile是一个制作镜像的脚本工具,通过它可以比直接拷贝docker容器更方便地迁移,只需要拷贝一个Dockerfile然后在本地构建一个即可。
1 | docker build -t local:mine . |
- 在Dockerfile中应该尽可能晚的添加应用程序源代码,才能充分利用layer的缓存。这意味着
COPY
这种命令尽量放到后面,并且尽量只COPY
需要的文件 - 尽量合并RUN命令,特别是
yum
等的更新安装命令,并且给加上–no-install-recommends
参数不安装不需要的依赖apt-get -y install --no-install-recommends 包名
- 为减小镜像大小可以移除安装缓存,
apt-get -y vim && rm -rf /var/lib/apt/lists/*
或者yum clean all
或者apt-get clean all
Dockerfile的语法说明:
1 | : Dockerfile中用#来进行注释 |
Docker Compose
Docker Compose主要用于快速在集群中部署分布式应用,主要有两个概念:
- 服务(Service): 一个应用的容器,实际上可以包括若干个运行相同镜像的容器实例
- 项目(Project): 由一组关联的应用容器组成的一个完整业务单元
linux需要单独安装该工具,其他平台安装教程
1 | sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
一个例子:
1 | weba: # 给容器取名 |
docker-compose常用命令
- 新版的命令好像直接就是
docker compose
而不是docker-compose
1 | docker-compose stop # 暂停所有容器 |
网络设置
1 | networks: # 与version同级 |
迁移
1 | docker save -o ubuntu_14.04.tar ubuntu:14.04 # 导出镜像到本地 |
容器网络
更改默认网桥bridge
的网段请参考本文TroubleShooting
1 | docker network ls # 列出所有的网桥 |
常用容器/镜像
- 如果是Mac M1或者其他ARM的机器,可以在dockerhub的左侧筛选
Architectures=ARM 64
即可,如果要使用mysql可以用mysql/mysql-server
Alpine
是一个非常简单的镜像,本身只有几兆,包含了linux最简单的内核,并且功能十分强大。很多的基础镜像都是基于它。当然,有一点特别注意,它没有自带apt-get,也没有bash(sh代替)。不过还好,也能使用阿里的镜像源。这里有它里面的一些基本操作
1 | apk add --update # 更新源 |
MySQL/Mariadb容器
AWS
的数据库跟Mariadb
数据库有些地方不兼容,最好用MySQL
1 | docker run --name some-mariadb -v /Users/haofly/share:/share --net host -e MYSQL_ROOT_PASSWORD=mysql -d mariadb:tag # 开启一个mysql容器,可通过exec bash进入容器内 |
PHP容器
- 如果网络有问题,那么可以在
https://github.com/richarvey/nginx-php-fpm
项目中的Dockerfile手动创建镜像
1 | docker run --name php-apache -v /Users/haofly/workspace/share/yangqing:/var/www/html -p 80:80 --link some-mysql:mysql -d b664eb500b48 # 这是php-apache,并且连接mysql容器,如果要安装mysql扩展需要在Dockerfile里面去安装 |
在PHP容器中安装PHP扩展
1 | docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql # mysql扩展 |
CentOS容器
1 | docker run -it -v /Users/haofly/workspace/dbm:/share --name dbm -d index.alauda.cn/library/centos:centos6.6 /bin/bash |
NodeJS容器
1 | docker run -it -v /Users/haofly/workspace:/workspace -p 4000:4000 -p 4001:4001 --name node -d node:latest /bin/bash |
Nginx代理
太好用了,这个
1 | 首先,直接拉下这个镜像并创建容器 |
Postgres容器
1 | docker run --name postgres -e POSTGRES_PASSWORD=the_password -p 5432:5432 -d postgres |
Ubuntu/Debian
- ubuntu如果要使用systemctl,需要安装init,可以在Dockerfile里面这样做
1 | RUN apt-get update && apt-get install -y init && apt-get clean all |
TroubleShooting
docker动态添加端口映射
方法一:此方法据说不安全,就是在run的时候--net host 方法二:在virtualbox中添加映射,这个其实没试验过
官方mysql镜像打开二进制日志
1
2
3
4
5
6
7
8docker run -v /var/lib/mysql:/var/lib/mysql \
mysql:5.7 \
mysqld \
--data \
--user=mysql \
--server-id=1 \
--log-bin=/var/log/mysql/mysql-bin.log \
--binlog_do_db=testCentOS7容器无法使用systemctl命令提示
Failed to get D-Bus connection: No connection to service manager.
/ 无法设置交换分区等错误。新版本默认不会提供特权模式,容器内部的root用户并不是真正的root用户,有很多权限都没有,可以在创建容器的时候添加特权模式docker run --privileged XXX /usr/sbin/init
出现
Exit status 255
错误,可能是虚拟机长期开启未关闭导致的,进入virtualBox将该docker machine关闭即可再次重新打开了时区不对: 不是相差8个小时这么简单,反正很乱
在新建容器的时候加上这个参数-v /etc/localtime:/etc/localtime:ro
**树莓派安装docker后出现错误
libapparmor.so.1: cannot open shared object file: No such file or directory
**,需要执行apt-get install lxc
更换docker网段: 目前存在的问题是docker容器的网段为
172.17.0.1/24
,但是公司的内网也是这个网段,导致冲突过后,我在我的容器里面ping不通别人的机器,所以就尝试着在mac上更换docker的默认网段。以前的版本是需要直接去修改~/Library/Containers/com.docker.docker/Data/database/com.docker.driver.amd64-linux/etc/docker/daemon.json
,但是新版本已经不能直接在那里修改了,修改网段更加方便了。直接在Preferences->Daemon->Advanced
里面的json文件进行修改(注意不是直接Preferences->Advanced)。1
2
3
4
5{
"debug" : true,
"experimental" : true,
"bip" : "192.168.1.5/24" // 默认网段是172.17.0.0/16,这里修改为一个不和内网冲突的网段即可
}Mac下
~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux
目录占用内存过大: 目测是一个一直没有被修复的bug,是由于镜像反复拉,容器反复删除重建,但是存储从来不释放造成的,可以尝试下面这些方法1
2
3
4
5
6
7
8docker run --privileged --pid=host docker/desktop-reclaim-space
docker system prune
如果还是觉得空间大了,可以将容器导出再导入试试
docker images | sed '1d' | grep -v '<none>' | awk '{print "docker save " $1 ":" $2 " -o " $3 ".tar"}' | bash # 导出
ls *.tar | xargs -I {} docker load -i {} # 导入
docker system df -v # 查看这些容器到底怎么占用磁盘的阿里源: 一般都是jessie版本,但是有些镜像的维护者可能会修改为一个比较小众的版本,可能导致某些包没有,这时候修改版本即可。
1
2
3
4
5
6
7
8
9基本上都是jessie,/etc/apt/sources.list
deb http://mirrors.aliyun.com/debian jessie main
deb http://mirrors.aliyun.com/debian jessie-updates main
deb http://mirrors.aliyun.com/debian-security jessie/updates main
alpine版本,/etc/apk/repositories
http://mirrors.aliyun.com/alpine/v3.7/main
http://mirrors.aliyun.com/alpine/v3.7/community
@testing http://mirrors.aliyun.com/alpine/edge/testingwindows找不到
/var/run/docker.sock
: 在最新的windows版本的docker里面,直接找是找不到这个文件的,需要添加环境变量COMPOSE_CONVERT_WINDOWS_PATHS = 1
Apache相关的容器可能意外退出后重新启动不起来,原因是意外退出,pid文件还在,需要在启动的时候添加一条命令:
rm -f /var/run/apache2/apache2.pid
dockerfile长文本
1
2
3echo "第一行\n\
第二行\n\
" > /etc/conf容器内部无网络: 首先可以使用
--net=host
使用主机的网络来检查是否是容器内部的网络问题,如果使用该参数依然无法访问网络,那么使用ping
直接ping
IP地址,如果IP通但是域名不通,那就是dns的问题,去查看一下容器的dns配置,一般目录是在/etc/resolv.conf
exited with code 0 容器没有任何报错就退出,日志也没有。有可能是因为该镜像的启动命令不是
daemon
方式,容器启动完成后立马就退出了,这个时候可以参照上面的-t
或者docker-compose
里面的tty: true
进行设置启动docker出现错误Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock dial unix /var/run/docker.sock: connect: permission denied: 可能权限有问题,可以这样修复:
1
2
3sudo groupadd docker
sudo usermod -aG docker ${USER}
然后该用户重新登录即可docker: Error response from daemon: network bridge is ambiguous (2 matches found on name). 本来这个一般发生在network网卡有重名的情况,一般用
docker network prune ID
就可以删除了,但偏偏我这次遇到的是默认的bridge
网卡重名,我也不知道怎么做到的,但是用prune
删除会报错,最后的方法是删除sudo mv /var/lib/docker/network/files/ /tmp/docker-network-bak
,然后重启systemctl restart docker
重新生成网卡解决了,注意最好先备份一下网卡信息apt-add-repository: command not found: 需要先安装:
apt-get install software-properties-common
没有cron: 容器默认是没有安装corntab服务的,需要自己手动安装,可以在dockerfile里面这样安装并添加自动执行任务:
1
2RUN apt-get install cron
RUN (crontab -l ; echo "*/5 * * * * /usr/bin/python3 /root/main.py >> /tmp/cron.log 2>&1") | crontab # 程序运行后定时任务会自动执行了w