我所有的网站代码都/srv
在我的容器中。
My Dockerfile 使用 git 下载代码,并使其成为映像的一部分,以便于部署到生产环境。
但是,如何在开发中编辑代码呢?我认为使用卷是解决方案,例如:-v /docker/mycontainer/srv:/srv
.但它会覆盖容器中的目录。如果这是我第一次运行它,它会清空它,因为主机中没有任何内容。因此,无论我在Dockerfile中所做的一切都丢失了。
/srv/myapp
中还有一些目录和文件,我希望在我的应用程序的不同版本之间共享,例如:/srv/myapp/user-uploads
.这是专业 Web 开发中的常见做法。
那么我能做些什么才能做到所有这些事情呢?
- 在开发中编辑/SRV 中的代码
- 在不同版本之间共享/SRV/myapp/用户上传
- 让 Dockerfile 下载代码。在我看来,在Docker之外做"git clone"或"git pull"会破坏Docker的目的。此外,还有一些我无法在主机中运行的内容,例如数据库迁移或其他特定于应用程序的脚本。
有没有办法进行反向卷装载?我的意思是让容器覆盖主机,而不是相反。
我认为一种解决方案可能是在运行容器的守护程序之前将/srv 复制到/srv.deployment-copy。然后,当我运行守护程序时,请检查/srv.deployment-copy 是否存在并将所有内容复制回/srv。这样,我就可以将/srv 用作卷,并且仍然能够使用 Dockerfile 将代码部署到其中。我已经为所有 docker 命令使用别名,因此自动化这不会有问题。你觉得怎么样?
我发现在开发中编辑代码的最佳方法是像往常一样安装所有内容(包括克隆应用程序的存储库),但移动容器中的所有代码以表示/srv/myapp.deploy.dev
。然后使用用于/srv/myapp
的rw
卷启动容器,以及一个 init.d 脚本来清理该卷并将新内容复制到其中,如下所示:
rm -r /srv/myapp/*
rm -r /srv/myapp/.[!.]*
cp -r /srv/myapp.deploy.dev/. /srv/myapp
rm -r /srv/myapp.deploy.dev
还有另一种方法可以从另一个容器启动带有卷的容器:
看
https://docs.docker.com/userguide/dockervolumes/创建和挂载数据卷容器
如果要在容器之间共享一些持久性数据,或者想要从非持久性容器使用,最好创建命名的数据卷容器,然后从中装载数据。
让我们创建一个新的命名容器,其中包含要共享的卷。
$ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
然后,可以使用 --volumes-from 标志将/dbdata 卷挂载到另一个容器中。
$ sudo docker run -d --volumes-from dbdata --name db1 training/postgres
另一个:
$ sudo docker run -d --volumes-from dbdata --name db2 training/postgres
我们可以对卷执行的另一个有用功能是将它们用于备份、还原或迁移。为此,我们使用 --volumes-from 标志创建一个挂载该卷的新容器,如下所示:
$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
====
=========我认为您不应该将主机目录挂载到容器中。但是您可以使用卷的所有功能。您可以使用其他容器以及完美的编辑器和工具集来编辑卷中的文件。容器这个你的应用将是干净的,没有开销。
结构为:
-) 应用数据的
容器 docker run -d -v /data --name data
-) 应用二进制文件的
容器 docker run -d --volumes-from data --name app1
-) 编辑器和开发
实用程序的容器 docker run -d --volumes-from data --name editor
注意:不能使用 -v
将容器目录挂载到主机目录。
我认为你不需要破坏/srv 和/srv.deployment-copy。如果你
我认为:
-
您应该将卷用于持久/共享数据:
-v /hostdir/user-uploads:/srv/myapp/user-uploads
,或者您可以使用数据卷容器概念。您可以将其视为存储在主机(仅数据容器)上的文件系统支持的数据库,并且容器被-v
允许使用它。 您是对的:对于生产部署 - 您可以使用源代码(
git clone
)构建映像,您可以为每个版本构建一个映像。应该不需要在生产中编辑源代码。对于开发环境 - 您应该在没有源代码的情况下构建映像,或者如果使用相同的映像进行部署/开发,则可以使用卷隐藏源代码目录。然后 git 在本地克隆源代码,并使用卷
-v /hostdir/project/src:/srv/project
与容器共享源代码。最好以只读方式共享源代码(:ro
末尾),任何临时或中间文件都应存储在容器中的其他位置。我在服务启动之前在容器启动时执行了设置脚本(数据迁移、重建一些索引/缓存数据文件等)。所以每当我觉得我需要新鲜的re-init
时,我只需杀死开发容器并再次运行它。或者,我不停止旧容器 - 我只是运行另一个容器。
我找到了一种仅使用 git 的好方法:
CONTAINER=my_container
SYNC_REPO=/tmp/my.git
CODE=/var/www
#create bare repo in container
docker exec $CONTAINER git init --bare $SYNC_REPO
#add executable syncing hook that checks out into code dir in container
printf "#!/bin/shnGIT_WORK_TREE=$CODE git checkout -fn" |
docker exec -i $CONTAINER bash -c "tee $SYNC_REPO/hooks/post-receive;chmod +x $_"
#use git-remote-helper to use docker exec instead of ssh for git
git remote add docker "ext::docker exec -i $CONTAINER sh -c %S% $SYNC_REPO"
#push updated local code into docker
git push docker master
假设您有一个包含代码的本地 git。Git 需要安装在容器中。或者,您可以使用docker run
和具有安装了 git 的共享卷的数据容器。
假设 git 不是容器的入口点,如果 git 安装在你的 docker 容器中,你可以 ssh 进入容器并运行 git clone
/git pull
。 由于卷与主机共享的方式,从容器到文件的更改也将对主机进行(实际上是相同的文件)。
以下是有关如何快速 ssh 到容器中的一些说明。