docker中COPY和VOLUME细节分析
COPY
COPY即复制的意思,和linux中的cp类似。linux中可复制如下
- 文件 ---》 文件夹
cp 1.txt /test
- 文件夹 ---》 文件夹
//将test文件夹下所有文件包括以及test目录复制到/test1 目录下
cp -r /test /test1
- 文件夹下所有文件 ---》文件夹
//将text目录下的所有文件都复制到test1目录
cp /test/* /test1
而不能
- 文件 ---》文件
- 文件夹 ---》文件
docker中的COPY和linux的类似,以Dockerfile为例。目标路径如果不存在(docker内的路径),不需要事先创建, docker会在复制文件前先创建目录确实目录
//文件复制到文件夹
COPY master.sh /etc/keepalived/
//将宿主机内/conf 目录下文件都复制到容器内目录为/etc/conf下
COPY /conf /etc/conf
和linux有点区别的是docker中COPY /conf /etc/conf,是指将宿主机内/conf 目录下所有文件都复制到容器内目录为/etc/conf下,和linux的cp /conf/* /etc/conf作用一样。
而不能如下,不然启动docker时候会报错
COPY master.sh /etc/keepalived/master.conf
COPY /conf /etc/conf/a.conf
注意:COPY命令写在Dockerfile中,属于Dockerfile,在docker-compose中没有该命令
VOLUME
docker中volume可以理解为linux中软连的意思,类似windows中快捷方式的概念。
在docker中可以
- 文件 volume 文件
redis:
container_name: laravel-redis1
build:
context: .
dockerfile: docker/redis1/Dockerfile
volumes:
- ./redis/redis.conf:/data/redis.conf
- 文件夹 volume 文件夹。如下代码,代表宿主机目录为./redis/data下的所有文件与容器目录为/data的所有文件建立软连关系
redis:
container_name: laravel-redis1
build:
context: .
dockerfile: docker/redis1/Dockerfile
volumes:
- ./redis/data:/data
而不能
- 文件 volume 文件夹
- 文件夹 volume 文件
注意:一定是文件软件文件,文件夹软连文件夹
在docker-compose.yml中 volume中的使用如下
redis:
container_name: laravel-redis1
build:
context: .
dockerfile: docker/redis1/Dockerfile
ports:
- 6380:6379
volumes:
- ./docker/redis1/data:/data
networks:
- laravel-network
volume用于docker-compose.yml中,不要用于Dockerfile中,不起作用
volume的时候通常有如下2情况
- 需要将宿主机的文件映射到容器内
如果目标路径以及文件不存在(容器内),容器内不需要事先创建, volume会在容器内自动创建并形成软连关系
- 需要将容器内的文件映射到宿主机上
宿主机同样不需要创建需要映射的文件以及目录。不管谁映射谁,宿主机和容器是双向的关联的
之前的操作是使用以下命令将容器内的文件copy到宿主机后在进行软连。其实不需要的,直接volume即可。
docker cp 容器id:容器文件路径 复制到宿主机的路径
权限问题
在实际过程中我们需要对某些文件增加权限操作,有俩种场景
- docker-compose.yml中volume的文件,需要在docker容器加权限。比如服务的日志文件
haproxy:
container_name: haproxy
build:
context: .
dockerfile: docker/haproxy/Dockerfile
ports:
- 8888:8888
volumes:
- ./haproxy/logs:/etc/haproxy/logs
networks:
- laravel-network
由于日志文件必须加写权限,不然写不进去,所以我们需要给容器内的执行命令
chmod -R 777 /etc/haproxy/logs
所以在Dockerfile中执行RUN命令,如下。遗憾的是/etc/haproxy/logs目录下的文件并没有获得777权限。
FROM haproxy:lasted
RUN chmod -R 777 /etc/haproxy/logs
所以如果是想给docker-compose.yml文件的volume文件加权限,我们可以在每次git拉取项目后,执行命令chmod -R 777 /etc/haproxy/logs,这次操作可以在自动化部署时加上该命令。
要知道volume不仅宿主机和docker的文件一致,而且权限也是一致的,所以在本地执行chmod -R 777 /etc/haproxy/logs后,在容器内相应的文件权限也会跟着改变
- Dockerfile中COPY的文件需要加权限
如果是Dockerfile中COPY的文件需要加权限,我们可以直接在Dockerfile中使用RUN指定赋予权限即可。
FROM haproxy:lasted
COPY /haproxy /data
RUN chmod -R 777 /data
以上加权限一定要注意,volume和copy的俩种方式,如果能使用copy,不需要软连的话,尽量使用copy即可
Dockerfile中的volume和docker-compose.yml中的volume的区别
Dockerfile中volume 定义匿名卷
格式如下:
- VOLUME ["<路径1>","<路径2>“]
- VOLUME <路径>
之前说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存到卷(volume)中,为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在Dockerfile中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向存储层写入大量数据。Dockerfile的VOLUME如下
VOLUME /data
这里的/data目录就会在运行时自动挂载为匿名卷,任何向/data中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置,比如
docker run -v mydata:/data
和docker-compose.yml中的作用一样
volumes:
- ./docker/redis1/data:/data