Vagrant managed docker container doesn't start - django

I've been trying to write a vagrant file to start up my docker container to run a small web app I've been writing. However when I try use vagrant up I eventually get an error saying
The container started either never left the "stopped" state or
very quickly reverted to the "stopped" state. This is usually
because the container didn't execute a command that kept it running,
and usually indicates a misconfiguration.
If you meant for this container to not remain running, please
set the Docker provider configuration "remains_running" to "false":
config.vm.provider "docker" do |d|
d.remains_running = false
end
I'm very new to vagrant so I'm not really sure what the best way to try and fix the problem is.
My vagrant file contains
Vagrant.configure("2") do |config|
config.vm.synced_folder "thelibrary", "/thelibrary"
config.vm.provider "docker" do |d|
d.image = "django-dev"
d.has_ssh = false
d.ports = ["8000:8000"]
d.cmd = ["python", "/thelibrary/manage.py", "runserver", "0.0.0.0:8000"]
end
end
I'm not sure why it says the command doesn't keep running. I can run the docker container with the same command and it will spin up my django app without any issues.

I had the same problem but adding option
d.create_args = ["-i"]
solved my problem

I spent the day try to get the docker machine running.. finally got it working. Here is what I have in my vangrantfile, hope this can at least get you started:
config.vm.provider :docker do |d|
d.image = "paintedfox/postgresql"
d.name = "db"
d.cmd = ["/sbin/my_init", "--enable-insecure-key"]
end
vagrant status returns me this:
Current machine states:
dev running (docker)
Another solution that you can try is to remove all your existing images and start fresh, it could be that your image is broken.

Related

Starting NginX with my modified nginx.conf on ECS

I have an environment in AWS with an ECS cluster, an EFS source and some services running on this cluster.
One of my services is the NginX web server which I use to serve our site and our services. As a solution to keep some sensitive and static configuration files we have chosen the EFS service. So, each service creates a volume from this EFS and mount it every time a container starts.
The problem is with NginX. I want to store my nginx.conf file into an EFS folder and after the NginX service starts, we want the container to copy this file at /etc/nginx/ folder in order for my NginX server to start with my configuration.
I've tried to build my own image including my configuration with success but this is not what we want.That means that we should build a new image every time we want to change a line on nginx.conf.
I've tried to create a script to run every time the container starts and copy my configuration but i didn't manage to make it play on ECS. Either the NginX failed to reload, either the syntax is wrong, either the file is not available.
#!/bin/bash
cp /efs/nginx.conf /etc/nginx/
nginx -s reload
Ι considered to find out how to create a cron job to run every X minutes and copy my nginx.conf to etc/nginx but this seems to be a stupid approach.
I made like 60 different task definitions revisions in order to find out how this CMD Environment option works on ECS. Of course the most of them has to do with the syntax and i get bach errors like "invalid option: bash" or "invalid option: /tmp/1.sh" etc
Samples:
1.Command ["cp","/efs/nginx.conf /etc/nginx/"]
2.Entry point ["nginx","-g","daemon off;"]
Command ["cp /efs/nginx.conf /etc/nginx/"]
Entry point: ["nginx","-g","daemon off"]
Command: ["/bin/sh","cp","/efs/nginx.conf/","/etc/nginx/"]
Command ["[\"cp\"","\"/efs/nginx.conf\"","\"/etc/nginx/\"]","[\"nginx\"","\"-g\"","\"daemon off;\"]"]
Command ["cp /efs/nginx.conf /etc/nginx/","nginx -g daemon off;"]
Command ["cp","/efs/nginx.conf /etc/nginx/","nginx -g daemon off;"]
-
Does anyone knows or does anyone already implement this solution on ECS?
To replace /etc/nginx/nginx.conf with a modified one from a binded volume?
Thanks in advance
SOLUTION:
As I mention at my question above, I'd like to use a static nginx.conf file, which will be into an EFS folder, into my nginx service container.
My task definition is simple like this
FROM nginx
EXPOSE 80
RUN mkdir /etc/nginx/html
Through ECS task definition I create a volume and then a mounting point which is an easy process and works fine. The problem was in the entrypoint field which supposed to include my script's directory and to my script itself.
At ECS task definition Environment entrypoint field i putted
sh,-c,/efs/docker-cmd-nginx.sh
and my script is just the following
#!/bin/dash
cp /efs/nginx.conf /etc/nginx/ &&
nginx -g "daemon off;"
PS: The problem probably was at:
my script which I didn't use double quotes at the daemon off; part but I was using double quotes on the whole line nginx -g daemon off;
my script was trying to reload nginx which was not even running yet.
my attempt to put the commands seperately at my task's entrypoint was wrong, syntax-wise for sure and maybe strategy-wise as well.

Supervisor on a Digital Ocean docker image

(beginner question)
I've successfully setup a nginx+gunicorn+django docker image on a Digital Ocean droplet.
My Django project follows the very good Cookie-Cutter-Django pattern (see here).
In this doc, there is a description of a supervisor install.
What I'm missing here is WHERE is the supervisor supposed to be running? Local or remotely?
I understand that if I install the supervisor on my laptop it will "keep-alive" my command "docker-compose up".
But what if I take 1 week off and my laptop runs out off battery?
Will the supervisor stop its job?
If so, I need to install it on my droplet, right?
Supervisor should run on your droplet. It will make sure that your webserver restarts automatically if it ever gets interrupted. An example configuration would be something like the following from this excellent blog post:
[program:hello]
command = /webapps/hello_django/bin/gunicorn_start ; Command to start app
user = hello ; User to run as
stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding
I was a bit confused.
This SO post was helpful : Is supervisord needed for docker+gunicorn+nginx?
As for this tuto: https://blog.codeship.com/ensuring-containers-are-always-running-with-dockers-restart-policy/
I've now added a "restart: always" on my compose.yml file:
redis:
image: redis:latest
restart: always

AWS: CodeDeploy for a Docker Compose project?

My current objective is to have Travis deploy our Django+Docker-Compose project upon successful merge of a pull request to our Git master branch. I have done some work setting up our AWS CodeDeploy since Travis has builtin support for it. When I got to the AppSpec and actual deployment part, at first I tried to have an AfterInstall script do docker-compose build and then have an ApplicationStart script do docker-compose up. The containers that have images pulled from the web are our PostgreSQL container (named db, image aidanlister/postgres-hstore which is the usual postgres image plus the hstore extension), the Redis container (uses the redis image), and the Selenium container (image selenium/standalone-firefox). The other two containers, web and worker, which are the Django server and Celery worker respectively, use the same Dockerfile to build an image. The main command is:
CMD paver docker_run
which uses a pavement.py file:
from paver.easy import task
from paver.easy import sh
#task
def docker_run():
migrate()
collectStatic()
updateRequirements()
startServer()
#task
def migrate():
sh('./manage.py makemigrations --noinput')
sh('./manage.py migrate --noinput')
#task
def collectStatic():
sh('./manage.py collectstatic --noinput')
# find any updates to existing packages, install any new packages
#task
def updateRequirements():
sh('pip install --upgrade -r requirements.txt')
#task
def startServer():
sh('./manage.py runserver 0.0.0.0:8000')
Here is what I (think I) need to make happen each time a pull request is merged:
Have Travis deploy changes using CodeDeploy, based on deploy section in .travis.yml tailored to our CodeDeploy setup
Start our Docker containers on AWS after successful deployment using our docker-compose.yml
How do I get this second step to happen? I'm pretty sure ECS is actually not what is needed here. My current status right now is that I can get Docker started with sudo service docker start but I cannot get docker-compose up to be successful. Though deployments are reported as "successful", this is only because the docker-compose up command is run in the background in the Validate Service section script. In fact, when I try to do docker-compose up manually when ssh'd into the EC2 instance, I get stuck building one of the containers, right before the CMD paver docker_run part of the Dockerfile.
This took a long time to work out, but I finally figured out a way to deploy a Django+Docker-Compose project with CodeDeploy without Docker-Machine or ECS.
One thing that was important was to make an alternate docker-compose.yml that excluded the selenium container--all it did was cause problems and was only useful for local testing. In addition, it was important to choose an instance type that could handle building containers. The reason why containers couldn't be built from our Dockerfile was that the instance simply did not have the memory to complete the build. Instead of a t1.micro instance, an m3.medium is what worked. It is also important to have sufficient disk space--8GB is far too small. To be safe, 256GB would be ideal.
It is important to have an After Install script run service docker start when doing the necessary Docker installation and setup (including installing Docker-Compose). This is to explicitly start running the Docker daemon--without this command, you will get the error Could not connect to Docker daemon. When installing Docker-Compose, it is important to place it in /opt/bin/ so that the binary is used via /opt/bin/docker-compose. There are problems with placing it in /usr/local/bin (I don't exactly remember what problems, but it's related to the particular Linux distribution for the Amazon Linux AMI). The After Install script needs to be run as root (runas: root in the appspec.yml AfterInstall section).
Additionally, the final phase of deployment, which is starting up the containers with docker-compose up (more specifically /opt/bin/docker-compose -f docker-compose-aws.yml up), needs to be run in the background with stdin and stdout redirected to /dev/null:
/opt/bin/docker-compose -f docker-compose-aws.yml up -d > /dev/null 2> /dev/null < /dev/null &
Otherwise, once the server is started, the deployment will hang because the final script command (in the ApplicationStart section of my appspec.yml in my case) doesn't exit. This will probably result in a deployment failure after the default deployment timeout of 1 hour.
If all goes well, then the site can finally be accessed at the instance's public DNS and port in your browser.

Vagrantfile with multiple vm and providers

I am trying to write a Vagrantfile with multiple machines backed up by multiple providers. I specifically want to be able to spawn more than one of those machines in one go. Basically I want to run the command:
vagrant up vb_vm aws_vm
I am aware of the --provider flag, but this would apply to all machines being spawned, so not applicable in my case.
This is my (very trimmed down but still valid) Vagrantfile:
Vagrant.configure(2) do |config|
config.vm.define 'vb_vm' do |vb_vm|
vb_vm.vm.box='ubuntu/trusty64' # from hashicorp
vb_vm.vm.provider :virtualbox do |v|
end
end
config.vm.define 'aws_vm' do |aws_vm|
aws_vm.vm.box = "aws/dummy"
aws_vm.vm.box_url = 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box'
aws_vm.vm.provider :aws do |a, override|
a.access_key_id = 'something'
a.secret_access_key = 'something'
a.ami='something'
end
end
end
A vagrant box list shows that the boxes used for each definitions are of the right type:
aws/dummy (aws, 0)
ubuntu/trusty64 (virtualbox, 20150928.0.0)
But a vagrant status gives me (note that I do have the lxc plugin available, which became the default)
Current machine states:
aws_vm not created (aws)
vb_vm not created (lxc)
So this shows that spawning multiple machine with multiple provider is indeed possible, but the choice of provider is wrong.
I am aware of the tricks to set up the default provider, but this only makes things worse (virtualbox used everywhere, aws not used at all...)
I am aware of old stackoverflow questions as well, but they are related to a much older version of Vagrant.
So the question is: how do I make sure that each box defined uses its proper provider?
The trick will be to create the VM with their own provider.
example: I've defined a quick Vagrantfile (minimized) with boxes for each provider
Vagrant.configure(2) do |config|
config.vm.define "db" do |db|
db.vm.box = "..."
db.vm.hostname = "db"
end
config.vm.define "app", primary: true do |app|
app.vm.box = "..."
app.vm.hostname = "app"
app.ssh.forward_agent = true
app.ssh.forward_x11 = true
app.vm.provider "vmware_fusion" do |vm|
vm.vmx["memsize"] = "4096"
end
end
end
I create each VM separately
fhenri#machine:~/project/examples/vagrant/multimachine$ vagrant up db --provider=virtualbox
Bringing machine 'db' up with 'virtualbox' provider...
....
fhenri#machine:~/project/examples/vagrant/multimachine$ vagrant up app
Bringing machine 'app' up with 'vmware_fusion' provider...
....
then I halt everything and next time I do vagrant up
fhenri#machine:~/project/examples/vagrant/multimachine$ vagrant up
Bringing machine 'db' up with 'virtualbox' provider...
Bringing machine 'app' up with 'vmware_fusion' provider...
and status looks good
fhenri#machine:~/project/examples/vagrant/multimachine$ vagrant status
Current machine states:
db running (virtualbox)
app running (vmware_fusion)
This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

docker dead but pidfile exists

I was working on docker on AWS instance and it was working fine. On one day, docker stopped working. When i restarted docker "service docker start", it started and "service docker status" returned "docker dead but pidfile exists" message and docker commands did not executed. When i inspected log file, it showed following messages:
msg="+job serveapi(unix:///var/run/docker.sock)"
msg="Listening for HTTP on unix (/var/run/docker.sock)"
msg="There are no more loopback devices available."
msg="loopback mounting failed"
To start docker, i removed pid file from /var/run/docker.pid, /var/run/docker.sock and also removed docker from /var/lock/subsys/docker and restarted docker. But no gain. It still gives same error on start "docker dead but pidfile exists".
Please help.
This ticket could be related with the loopback issue.
https://github.com/docker/docker/issues/7058
So, please check output from losetup -l and ls -l /dev/loop*
EDIT: If ls -l /dev/loop* returns an error, most likely cause is the github ticket I indicated, and then you would need something like
#!/bin/bash
for i in {0..6}
do
mknod -m0660 /dev/loop$i b 7 $i
done
(taken from the mentioned issue)
Also, if you only want to restart, you may need to umount /var/lib/docker/devicemapper or any mounted volume of type aufs