Up and down a docker container while app is running in Rails - ruby-on-rails

I have a container that i just want it to come up a certain time of the day, after that I want it to stop (I'm using rails)
Can i create a control variable for him?
Ex:
At 00 am until 01 am he's running, after that the variable turning into false and just that container stop.
The docker-compose that I using for it:
sentiment-analyzer:
build: ./sentiment-analyzer
container_name: sentiment-analyzer
ports:
- "8000"
volumes:
- ./sentiment-analyzer-mock:/app
tty: true
stdin_open: true
I'm using that docker for text analyze with BERT in python. So, in that time i want send texts and recive the result.
The rest of the time it would only consume memory if it kept running, so I want it to only go up at that time...

Related

Docker Compose - Is it possible to update all changed images with a single command?

I have a compose.yml like this one:
version: '3.7'
services:
nginx:
restart: unless-stopped
image: ghcr.io/user/frontend:latest
ports:
- 80:80
depends_on:
- backend
backend:
restart: unless-stopped
image: ghcr.io/user/backend:latest
entrypoint: /home/app/web/wsgi-entrypoint.sh
expose:
- 8000
We have 2 images stored on Github: frontend and backend.
My goal is the following: when an image has been updated on the Github Docker Registry, I'd like to automatically update the image on the server and launch the new one substituting the old one via docker-compose.
For example: I have a running compose made by frontend and backend, but I just pushed a new image: ghcr.io/user/frontend:latest.
Now, I want a single command which updates only the images that have been changed (in this case ghcr.io/user/frontend:latest) and when I reload the frontend webpage I see the changes.
My attempt is the following:
docker-compose up -d --build
But the system says:
compose-backend_1 is up-to-date
compose-nginx_1 is up-to-date
which is not true!
So, the working procedure I use is a bit manual:
docker pull ghcr.io/user/frontend:latest
I see in the console: Status: Downloaded newer image,
which is the proof that a new image has been downloaded.
Then, if I relaunch the same command the console displays: Status: Image is up to date for ghcr.io/user/frontend:latest
Finally:
docker-compose up -d --build
says: Recreating compose-nginx_1 ... done
I suppose the command docker-compose up -d --build ALONE is not looking for new images and so does not update the image that is changed.
So, is there a SINGLE specific command to fix this?
Should be achieved by running docker-compose pull, and then docker-compose up -d
Or, shorter: docker-compose up -d --pull always
You can use variable substitution in many places in a docker-compose.yml file, in particular including the image:. If you give every build a unique tag, then you can supply the tag as an environment variable, and it will work the way you describe.
Let's say the two images have the same tagging scheme (they don't necessarily need to). You could update the Compose file to say
version: '3.8'
services:
nginx:
restart: unless-stopped
image: ghcr.io/user/frontend:${TAG:-latest} # <--
ports:
- 80:80
depends_on:
- backend
backend:
restart: unless-stopped
image: ghcr.io/user/backend:${TAG:-latest} # <--
Notice the $TAG reference at the end of the image: lines. If TAG isn't set in the environment, it will use latest, but if it is, it will use that exact build.
Now, if I run:
TAG=20221020 docker-compose up -d
For both containers, Compose will notice that they're running an older build, automatically pull the updated image from GitHub, and restart both containers against the newer image.
This brings the mild complication of your continuous-deployment system needing to know the current image tag. In exchange, though, you get the ability to very easily roll back – if today's build turns out to have a critical bug you can run the exact same command with a different tag to redeploy on yesterday's build. A setup like this is also necessary if you're considering migrating to Kubernetes, since it depends on the text of the image: string changing to trigger a redeployment.

CosmosDb Emulator with docker-compose

I can successfully bring up a CosmosDb Emulator instance within docker-compose, but the data I am trying to seed has more than 25 static containers, which is more than the default emulator allows. Per https://learn.microsoft.com/en-us/azure/cosmos-db/emulator-command-line-parameters#set-partitioncount you can set this partition count higher with a parameter, but I am unable to find a proper entrypoint into the compose that accepts that parameter.
I have found nothing in my searches that affords any insight into this as most people have either not used compose or not even used Docker for their Cosmos Emulator instance. Any insight would be appreciated.
Here is my docker-compose.yml for CosmosDb:
services:
cosmosdb:
container_name: "azurecosmosemulator"
hostname: "azurecosmosemulator"
image: 'mcr.microsoft.com/cosmosdb/windows/azure-cosmos-emulator'
platform: windows
tty: true
mem_limit: 2GB
ports:
- '8081:8081'
- '8900:8900'
- '8901:8901'
- '8902:8902'
- '10250:10250'
- '10251:10251'
- '10252:10252'
- '10253:10253'
- '10254:10254'
- '10255:10255'
- '10256:10256'
- '10350:10350'
networks:
default:
ipv4_address: 172.16.238.246
volumes:
- '${hostDirectory}:C:\CosmosDB.Emulator\bind-mount'
I have attempted to add a command in there for starting the container, but it does not accept any arguments I have tried.
My answer for this was a work around. Ultimately, running windows and linux containers side-by-side was a sizeable pain. Recently, Microsoft put out a linux container version of the emulator, which allowed me to provide an environment variable for partition counts, and run the process far more efficiently.
Reference here: https://learn.microsoft.com/en-us/azure/cosmos-db/linux-emulator?tabs=ssl-netstd21

Docker compose run multiple commands one after another

I recently started working with docker-compose and I am running into an issue where I won't get any helpful answers while googling. So what I want to do is running 2 commands on after another. First I want to train my model which places a trained model in a folder. The second command then runs the model. However, right now both commands start together and the image is loaded twice as well as the volume is created twice.
So my question is if it is possible to run multiple commands one after another, how does that work? I wonder as well, how my trained model is put into the volume docker-compose is running on? Can I somehow set a path to that volume as an output?
My docker-compose file so far:
version: '3.3'
networks: {rasa-network: {}}
services:
rasa:
image: rasa/rasa:latest-full
ports:
- "5005:5005"
volumes:
- ./rasa/:/app/
command: run -vv -m models/test_model/ --enable-api --endpoints endpoints.yml --credentials credentials.yml
networks: ['rasa-network']
depends_on:
- training
- duckling
duckling:
image: rasa/duckling:latest
ports:
- "8000:8000"
networks: ['rasa-network']
training:
build: .
image: rasa/rasa:latest-full
command: train --data data/ -c config.yml -d domain.yml --out models/test_model
volumes:
- ./rasa/:/app/
According to the documentation of depends_on, Docker compose is not able to determine the readiness of a container, so as soon as the dependencies have started, the last container will start, ignoring if the other ones are ready or not.
The workaround you could do is to do a wrapper shell script that controls that the dependencies (duckling and training) have finished doing their stuff before starting rasa. This means, if rasa needs some files from the other two containers, you can create an script to check if these files exist with a loop. If so, exit the loop and run the command you have. Otherwise, sleep some seconds and retry.
Then, the rasa command would execute only this script, for example:
command: ["./wait-for-dependencies.sh", "duckling", "training"]
You can have a look here: https://docs.docker.com/compose/startup-order/, they have made some examples for a similar use-case.

Rails 5+, WebPacker and Docker development workflow

One of the advantages of using Docker is single environment for entire team. Some time ago I was using Vagrant to unify development environment in a team, and it worked pretty well. Our workflow was like:
Run vagrant up, command takes some time to download the base image, run provisioning scripts. It also maps directory from local filesystem to container filesystem.
Change file on the host system, all changes will be mapped to guest filesystem (container), so no container restart needed.
Some folks use Docker for the similar development workflow, but I usually use docker-compose just to run satellite services. And I was always running Rails monolith inside of host operating system, like natively.
So my development workflow is pretty standard:
All the satellite services are up and located inside of Docker containers, I just have a bunch of exposed ports. I don't need to brew-install lots of software to support them, it's good.
Rails monolith runs in host OS, so every time I make, for example, JavaScript file change, WebPacker comes into play, rebuilds, and applies changes without page refresh. It's important to emphasize, because page refresh takes time, I don't want to refresh the page every time I do JavaScript or CSS file change.
With Vagrant the above scheme works well as well. But with Docker things are different.
The development workflow some folks use with Docker is as follows:
Run a bunch of services with docker-compose command, except Rails monolith (same step as with my development workflow above).
Every time you make change in your app (for example, JavaScript file) you need to rebuild container, because you're making changes on your local filesystem, not inside of a docker container. So you 1) stop 2) build 3) run Docker container again.
In other words, with Docker-only approach we have the following cons:
No webpacker js/css refresh
Container rebuild, which takes time
Application restart, which takes a lot sometimes, even zero-code "Rails" app starts in ~3 seconds
So my question is: what's the best way to go with Docker-only approach? How you can take advantage of Docker while using WebPacker with Rails and avoid page refresh and application restart?
I've been reading a good book on this recently (Docker for Rails developers). The gist seems to be that you run Rails in a Docker container and use a volume to 'link' your local files into the container, so that any file changes will take immediate effect. With that, you should not need to restart/rebuild the container. On top of that, you should run webpack-dev-server as a separate container (which also needs the local files mounted as a volume) which will do JavaScript hot reloading - so no need to reload the page to see JS updates.
Your docker-compose.yml file would look something like this (uses Redis and Postgres as well):
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/usr/src/app
env_file:
- .env/development/web
- .env/development/database
environment:
- WEBPACKER_DEV_SERVER_HOST=webpack_dev_server
webpack_dev_server:
build: .
command: ./bin/webpack-dev-server
ports:
- 3035:3035
volumes:
- .:/usr/src/app
env_file:
- .env/development/web
- .env/development/database
environment:
- WEBPACKER_DEV_SERVER_HOST=0.0.0.0
redis:
image: redis
database:
image: postgres
env_file:
- .env/development/database
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:

Pass unique id to Docker Compose service instance

I have to deploy a third-party web application with front server acting like load balancer and multiple instances of the actual app server behind it. For reasons independent from me I must pass unique id to each app server instance, as environmental variable. My docker-compose.yml, simplified, is as follows:
version: '3'
services:
lb:
image: lb_image
app:
image: app_image
depends_on:
- lb
links:
- "server:lb"
environment:
- LB_HOST=server
Now, I'd like to run:
docker-compose up -d --scale app=3
but passing to each instance different env variable value. I've heard of templating, it would be nice to have something like:
environment:
- CONTAINER_ID={{.Node.Id}}
in my docker-compose.yml, is it possible (every solution I've heard of this far involves writing external script, which in my opinion totally discards benefits of using Compose)?

Resources