11

Our application is containerized and using docker swarm as an orchestrator. I wanted to understand how do we promote docker images from dev, qa, uat and to production. For example, if I have an image created in dev as test:10 (10 is the build number generated by jenkins). How can I promote the same image to qa, uat and production? We are currently using NEXUS as a docker repository. What I don't understand is how will I pull the exact image which is being used in the dev environment. Can anyone help with this?

arun Kaliappan
  • 113
  • 1
  • 6
  • can you expand on why `docker pull org/test:10` doesn't work? Images are immutable after build, so it should be straightforward. – meatspace Feb 21 '18 at 19:58
  • Yes, it should work if I run this command manually. My requirement is if there are 5 microservices running in Dev environment I need to promote images which are there in Dev environment to QA environment automatically. – arun Kaliappan Feb 21 '18 at 22:14
  • @meatspace image tags are mutable though, they can be changed to refer to any immutable image checksum. – Matt Feb 22 '18 at 09:02
  • @arunKaliappan This isn't really a Docker or Nexus question, you probably need a Jenkins jobs that fits in your continuous deployment pipeline to allow someone to either input the version, or query the source environment. Without a specific description of your environment and Jenkins deployments it's hard to give a specific answer. – Matt Feb 22 '18 at 09:08
  • 1
    have you solved this issue ? – Mostafa Hussein Sep 20 '19 at 22:51

4 Answers4

8

You can promote an image from one docker image repository to another by retagging your image and pushing:

docker build -t my-test .
docker tag my-test your-image-repository-dev/test:10
docker login "your-image-repository-url"
docker push your-image-repository-dev/test:10
# ... deploy/test your image in dev
docker pull your-image-repository-dev/test:10
docker tag your-image-repository-dev/test:10 \
           your-image-repository-qa/test:10
docker push your-image-repository-qa/test:10

You will then have the same image in a QA docker image repository. This makes sense for images that have passed a base level of unit/functional/user acceptance tests which are distinct from images that have not! The key concept here being the timing at which you retag and push your image. Further, specifying image pull credentials for each docker image repository can help you limit the images that can actually make it to specific environments.

An alternative to the strategy above is that, you might not have separate docker image repositories, and may opt for changing the image name instead of the repository. In this case, you might do the following.

docker build -t my-test .
docker tag my-test your-image-repository/test:10
docker login "your-image-repository-url"
docker push your-image-repository/test:10
# ... deploy/test your image in dev
docker pull your-image-repository/test:10
docker tag your-image-repository/test:10 \
           your-image-repository/test-qa:10
docker push your-image-repository/test-qa:10
rjminchuk
  • 899
  • 9
  • 13
0

One approach to this problem is to use a CI/CD tool such as Jenkins or even some CI/CD bash scripts and have a sort of tagging strategy. As you may know, you can tag the same image differently. For instance, you can have a built image ID of 0000 and tag that many times as follow:

Day 1:
| TAG         | IMAGE ID |
| test:10     | 00000000 |
| test:dev-latest | 00000001 |
| test:qa-latest  | 00000001 |
| test:prod-latest| 00000001 |    

Day 2:
| TAG             | IMAGE ID |
| test:10         | 00000000 |
| test:11         | 00000001 |
| test:dev-latest | 00000001 |
| test:qa-latest  | 00000001 |
| test:prod-latest| 00000001 |

And your orchestrator can always wait for the new images to be tagged. This method theoretically is useful. However, based on your container orchestrator specific feature you can slightly refine this approach to use those specific features. For instance, image pulling policies, or rollout and rollback feature, features to implement blue/green strategy, etc.

0

The key is to use some form of metadata in your image tags to indicate which step of your deploy process an image corresponds to. There are many potential ways to do this, but maybe look at SemVer first, as it is a well documented and fiarly widely used option.

https://semver.org/

The main thing to pay attention to in semver is the use of a - marker in a version, which indicates that something is a "pre-release" version.

With this in mind, it's easy to separate production and non-production images:

  • Production version: nginx:1.2.3
  • Non-production version: nginx:1.2.3-10

From there, you can break down your non-production versions further if needed through the use of "dot-separated pre-release identifiers"

  • dev: nginx:1.2.3-dev.10
  • qa: nginx:1.2.3-qa.10
  • uat nginx:1.2.3-uat.10

There's other tagging methods you could use, but SemVer is well documented, widespread, and solves the problem.

Swiss
  • 5,556
  • 1
  • 28
  • 42
0

A best practice is to have a separate container repository for each environment. Docker pull onto the build/release agent may not be required with Azure Container Registry. I have written a article on this promoting-container-images-to-production-using-azure-devops

samdinesh
  • 147
  • 1
  • 3
  • 9
  • I'm wondering if you could elaborate a bit why it's the best practice to have a separate container repository for each environment VS having separate tags as @Swiss described – XZen Feb 13 '23 at 10:02
  • Separation of the environment is good at least between Prod and Non-Prod environments but if you can manage one for each environment it will be helpful - Keeping the registry close to the pull app/service - high availability of Prod registry - housekeeping of older or unused images – samdinesh Feb 15 '23 at 08:33