I won't put ketchup in my burger, and I certainly won't put multi-line shell code in my yaml. I don't want to add all that stuff into my compose file. First we start dependencies and then run the e2e_tests. Voilà! Not only does this address our race condition, but it's also very intuitive and easy to follow. What this means is that, immediately after running the start_dependencies service, e2e_tests can be started with certainty that web is ready to accept connections right away.Ĭreating network "your_project_default" with the default driverĬonnection to web 8080 port succeeded! Once successful, the loop terminates, the message "Connected!" is printed to the terminal, and the service terminates.ĭocker Compose will ensure that the dependent service ( web) remains running even after this container terminates. This service attempts to make a TCP connection to port 8080 of the web container and loops until it is successful, sleeping 1 second on each loop. Let's run this and confirm our expectations: If you try running e2e_tests then you will see a message about web container being created, but the e2e tests will fail to run because they will not be able to make a connection to web. Next, we have e2e_tests which, upon startup, immediately try to connect to web ( nc -z web 8080). This mimics the delay that a typical service may incur when starting up cold. After the sleep, it is ready to accept incoming TCP connections on port 8080 ( nc -lk 0.0.0.0 8080). What we have here is a service called web that simulates a delayed startup time by sleeping for 5 seconds ( sleep 5). To demonstrate this, let us first modify our existing docker-compose.yml file a bit so that we introduce the race condition. Although you don't get anything out-of-the-box that allows you to say "this service depends on this open port of that service," the tools for introducing such behavior are right in front of you: simply introduce a "port-checking" service. When running something such as end-to-end tests, it would be nice to just assume that thing they're testing is running and accepting connections.Īn alternative is to lean on the tools that you're already using to containerize your apps: Docker Compose. You're adding more and more "stuff" to the container that it otherwise wouldn't have. Reason being is that it gives your tests knowledge of the fact that they live in some sort of containerized world where the services it depends on was literally just started and needs some time to warm up. It's pretty trivial to add some "preload" block of code to e2e_tests startup code so that it tries to connect to the web service, then retries, and sleeps, and tries again and again until it succeeds.Īlthough this will work, it's not ideal. One workaround is to modify our e2e_tests startup script so that it has knowledge of this fact and does something about it. Because both services start at the same time, it is possible that the e2e_tests attempt to initiate a connection to the web service before the web service is ready to accept connections. In our case here, Docker Compose only guarantees that the web service had its "power button pressed," but not that the web server is actually ready to start accepting connections it still has to go through its regular startup procedure and do a few things before it's actually "ready for use." What Docker Compose guarantees is that dependency services are started in the same sense that your desktop computer is started when you press the power button–it still takes a while for the computer to get through its startup screens before you actually get a login screen and the computer is "ready for use." The problem is that "start," in this context, does not mean what we typically want it to mean. When you docker-compose run my_e2e_tests, Docker Compose will start your e2e_tests and your web service.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |