Go applications fails and exits when running using docker-compose, but works fine with docker run command - docker

I am running all of these operations on a remove server that is a
VM running Ubuntu 16.04.5 x64.
My Go project's Dockerfile looks like:
FROM golang:latest
ADD . $GOPATH/src/example.com/myapp
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
#CMD ["./myapp"]
When I run the docker container using docker-compose up -d, the Go application exits and I see this in the docker logs:
myapp_1 | /bin/sh: 1: ./myapp: Exec format error docker_myapp_1
exited with code 2
If I locate the image using docker images and run the image like:
docker run -it 75d4a95ef5ec
I can see that my golang applications runs just fine:
viper environment is: development HTTP server listening on address:
":3005"
When I googled for this error some people suggested compiling with some special flags but I am running this container on the same Ubuntu host so I am really confused why this isn't working using docker.
My docker-compose.yml looks like:
version: "3"
services:
openresty:
build: ./openresty
ports:
- "80:80"
- "443:443"
depends_on:
- myapp
env_file:
- '.env'
restart: always
myapp:
build: ../myapp
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
ports:
- "3005:3005"
depends_on:
- db
- redis
- memcached
env_file:
- '.env'
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- "/home/deploy/v/redis:/data"
restart: always
memcached:
image: memcached
ports:
- "11211:11211"
restart: always
db:
image: postgres:9.4
volumes:
- "/home/deploy/v/pgdata:/var/lib/postgresql/data"
restart: always

Your docker-compose.yml file says:
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
which means your host system's source directory is mounted over, and hides, everything that the Dockerfile builds. ./myapp is the host's copy of the myapp executable and if something is different (maybe you have a MacOS or Windows host) that will cause this error.
This is a popular setup for interpreted languages where developers want to run their application without running a normal test-build-deploy sequence, but it doesn't really make sense for a compiled language like Go where you don't have a choice. I'd delete this block entirely.

The Go container stops running because of this:
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
You are switching directories to $GOPATH/src/example.com/myapp where you build your app, however, your entry point is pointing to the wrong location.
To solve this, you either copy the app into the root directory and keep the same ENTRYPOINT command or you copy the application to a different location and pass the full path such as:
ENTRYPOINT /my/go/app/location

Related

Can't access web container from outside (Windows Docker-Desktop)

i'm using Docker-Desktop on Windows and i'm trying to get running 3 containers inside docker-desktop.
After few research and test, i get the 3 container running [WEB - API - DB], everything seems to compile/run without issue in the logs but i'can't access my web container from outside.
Here's my dockerfile and docker-compose, what did i miss or get wrong ?
[WEB] dockerfile
FROM node:16.17.0-bullseye-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
CMD ["npm", "run", "start"]
[API] dockerfile
FROM openjdk:17.0.1-jdk-slim
WORKDIR /app
COPY ./target/test-0.0.1-SNAPSHOT.jar /app
#EXPOSE 2022 (the issue is the same with or without this line)
CMD ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
Docker-compose file
version: "3.8"
services:
### FRONTEND ###
web:
container_name: wallet-web
restart: always
build: ./frontend
ports:
- "80:4200"
depends_on:
- "api"
networks:
customnetwork:
ipv4_address: 172.20.0.12
#networks:
# - "api"
# - "web"
### BACKEND ###
api:
container_name: wallet-api
restart: always
build: ./backend
ports:
- "2022:2022"
depends_on:
- "db"
networks:
customnetwork:
ipv4_address: 172.20.0.11
#networks:
# - "api"
# - "web"
### DATABASE ###
db:
container_name: wallet-db
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
customnetwork:
ipv4_address: 172.20.0.10
#networks:
# - "api"
# - "web"
networks:
customnetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# api:
# web:
Listening on:
enter image description here
I found several issue similar to mine but the solution didn't worked for me.
If i understand you are trying to access on port 80. To do that, you have to map your container port 4200 to 80 in yaml file 80:4200 instead of 4200:4200.
https://docs.docker.com/config/containers/container-networking/
Have you looked in the browsers development console, if there comes any error. Your docker-compose seems not to have any issue.
How ever lets try to debug it:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6245eaffd67e nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:4200->80/tcp test-api-1
copy the container id then execute:
docker exec -it 6245eaffd67e bin/bash
Now you are inside the container. Instead of the id you can use also the containers name.
curl http://localhost:80
Note: in my case here i just create a container from an nginx image.
In your case use the port where your app is running. Control it in your code if you arent sure. A lot of Javascript-frameworks start default on 3000.
If you get an error: curl command not found, install it in your image:
FROM node:16.17.0-bullseye-slim
USER root # to install dependencies you need sudo permissions su we tell the image that it is root
RUN apt update -y && apt install curl -y
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
USER node # we dont want to execute the image as root so we put user node (this user is defined in the node:16.17.0-bullseye-slim image)
CMD ["npm", "run", "start"]
Now the curl should work (if it doesnt already).
The same should work from your host.
Here is an important thing:
The localhost, always refers to the fisical computer, or the container itselfs where you are refering. Every container and your PC have localhost and they are not the same.
In the docker-compose you just map the port host/container, so your PC (host) where docker is running can access the docker network from the host on the host port you defined, inside the port of the container.
If you cant still access from your host, try to change the host ports 2022, 4200 ecc. Could be possible that something conflicts on your Windows machine.
It happens sometimes that the docker networks can create some conflicts.
Execute a docker-compose down, so it should be delete and recreated.
Still not working?
Reset docker-desktop to factory settings, control if you have last version (this is always better).
If all this doesnt help, let me know so we can debugg further.
For the sake of clarity i post you here the docker-compose which i used to check. I just used nginx to test the ports as i dont have your images.
version: "3.8"
services:
### FRONTEND ###
web:
restart: always
image: nginx
ports:
- "4200:80"
depends_on:
- "api"
networks:
- "web"
### BACKEND ###
api:
restart: always
image: nginx
ports:
- "2022:80"
depends_on:
- "db"
networks:
- "api"
- "web"
### DATABASE ###
db:
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
- "api"
networks:
api:
web:
```
Update:
You can log what happens in the conatiner like so:
```
docker logs containerid/name
```
If you are using Visualcode there is excellent extension for docker build also by Microsoft:
Just search docker in the extensions. Has something like 20.000.000 downloads and can help you a lot debugging containers ecc. After installing it you see the dockericon on the left toolbar.
If you can see directly the errors that occurs in the logs, maybe you can post them partially. So it would be possible to understand. Please tell also something about your Frontendapp architecture, (react-app, angular). There are some frameworks that need to be startet on 0.0.0.0 instead of 127.0.0.1 or they dont work.

Docker Compose Failing for command

Dockerfile:
FROM hseeberger/scala-sbt:8u222_1.3.5_2.13.1
WORKDIR /code/SimpleStocks
COPY ./SimpleStocks .
RUN sbt dist
WORKDIR /code/SimpleStocks/target/universal
RUN unzip simplestocks-0.0.1.zip
WORKDIR /code/SimpleStocks/target/universal/simplestocks-0.0.1
CMD ["bin/simplestocks"]
docker-compose.yml:
version: "3.7"
services:
app:
container_name: simple-stocks
image: simple-stocks:1.0.0
build: .
ports:
- '9000:9000'
volumes:
- .:/code
links:
- pgdb1
pgdb1:
image: postgres
environment:
POSTGRES_DB: simple_stocks
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- pgdb1data:/var/lib/postgresql/data/
- ./docker_postgres_init.sql:/docker-entrypoint-initdb.d/docker_postgres_init.sql
ports:
- '5432:5432'
volumes:
pgdb1data:
When I manually run simple-stocks container using docker run -it {imageId}, I am able to run it successfully; but, on doing docker compose up I am receiving:
Error response from daemon: OCI runtime create failed:
container_linux.go:380: starting container process caused: exec:
"bin/simplestocks": stat bin/simplestocks: no such file or directory:
unknown
Your Dockerfile is building the application in /code/SimpleStocks/target/universal/simplestocks-0.0.1, but then your Compose file bind-mounts a host directory over /code, which hides everything the Dockerfile does. The bind mount is unnecessary and deleting it will resolve this issue.
Bind-mounting a host directory over your entire built application usually is not a best practice. I most often see it trying to convince Docker to emulate a local development environment, but even that approach doesn't make sense for a compiled language like Scala.
You can safely remove the volumes: block. The obsolete links: can also be removed. You don't need to manually specify container_name:, nor do you need to specify both build: and image: unless you're planning to push the built image to a registry. That would reduce the Compose setup to just:
version: '3.8'
services:
app:
build: .
ports:
- '9000:9000'
pgdb1: (as in the question originally)
volumes:
pgdb1data:

Unable to access site in docker-compose

I've been using: docker build -t devstack .
docker run --rm -p 443:443 -it -v ~/code:/code devstack
That has been working fine for me so far. I've been able to access the site as expected through my browser. I set my hosts file to point devstack.com to 127.0.0.1 and the site loads nicely. Now I'm trying to use docker-compose so I can use some of the functionality there to more easily connect with AWS.
services:
web:
build:
context: .
network_mode: "bridge"
ports:
- "443"
- "80"
volumes:
- ~/code:/code
image: devstack:latest
So I run docker-compose build which gives me the familiar build stuff from Dockerfile.
Then I run docker-compose run web which puts me into the VM where I start apache (doing it manually at the moment), hit top to verify it’s running, then tail the log files. But when I attempt to hit the site in my browser, I get: devstack.com refused to connect. and no logs in the apache log files, so it's not even getting to apache. So something about the ports isn't opening up to me. Any idea what I need to change to make this work?
Edit: Updated file. Still same problem:
version: "3"
services:
web:
build:
context: .
# Same issue with both of these:
# network_mode: "bridge"
# network_mode: "host"
ports:
- "443:443"
- "80:80"
volumes:
- ~/code:/code
tty: true
This is what I did to get it working. I used the example project docker-compose showed in their documentation, which runs a test app on port 5000. That worked, so I knew it could be done.
I updated my docker-compose.yml to be very similar to the one in the test project. So it looks like this now:
version: "3"
services:
web:
build: .
ports:
- "443:443"
- "80:80"
volumes:
- ~/code:/code
Then I created an entry.sh file which will start apache, and added this to my Dockerfile:
# copy the entry file which will start apache
COPY entry.sh entry.sh
RUN chmod +x entry.sh
# start apache
CMD ./entry.sh; tail -f /var/log/apache2/*.log
So now when I do docker-compose up, it will start apache and tail the apache log files. So I immediately see apache log files output to terminal. Then I'm able to access the site. Basically the problem was just with the VM exiting. This was the only way I could find to keep it from exiting without doing tty=true in the docker-compose, which while it kept it from exiting, wouldn't publish the ports.

Docker - no access to other containers in the network during docker image build

I have two docker containers: simple rest api and a database. I want to start the rest api only when the database is ready. I tried several solutions, when i figured out the problem is in the network.
wait-for-it.sh script works perfectly fine when I start rest api without waiting for the database and then do docker exec -it <api-container-name> bash and run it from there. When I'm trying to run it as a CMD in Dockerfile it can't establish connection with the database. Same thing happens when I start the api while database is already running.
Api dockerfile:
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN chmod +x Scripts/wait-for-it.sh
RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306 #times out when waiting for database
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
docker-compose:
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
I see your confusion.
The RUN statement isn't doing what you think it is; it's running the wait-for-it.sh while the container is building, and isn't under the docker-compose's control. It will not run when your container runs! You should check out the documentation from docker about container start-up order and docker-compose.
Detached mode for your database will have no effect on build/run process; expect you won't be able to interact with it.
Using docker-compose will, by default, have all the container in non-interactive mode; but that's okay because you can still attach/detach to the containers.
You should add a depends-on option to your docker-compose.yml and add your wait-for-it.sh to the command option in the docker-compose.yml, not the Dockerfile.
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
# Add this `depends-on`
depends-on:
- "main-db"
# Add this `command` option
command: ["Scripts/wait-for-it.sh", "-t", "30", "172.20.1.2:3306"]
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
I would recommend moving wait-for-it.sh to your WORKDIR, and make sure it is passed as "./wait-for-it.sh" to command, just to make your life easier.
Don't forget to remove RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306 from your Dockerfile! (Because docker-compose is handling it now.)
And remember that the command for using docker-compose is docker-compose up, unless, that is, you'd like to use docker swarm instead.
Well. I managed to solve my problem. I can guess this is not a clean way of doing it, but it works for now.
I'm building and running both containers first. Then, when both api and db are up, i'm remotely executing migration commands using docker exec. wait-for-it script is not needed here.
run.sh
#!/bin/bash
docker-compose up -d --build atlanta-ms main-db
docker exec atlanta bash -c "dotnet ef migrations add InitialMigration && dotnet ef database update"
rest api Dockerfile
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
docker-compose.yml
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
The drawback of this solution is that rest api is running in detached mode, so i cannot stop it just by doing ctrl + c in console. Adding docker attach atlanta line at the end of run.sh script works (i can stop container by simple ctrl + c), but it doesn't work with several containers (cannot attach to more than one container) so i have to write simple stop script and call it independently from run.sh to stop containers, what is a little inconvenient.
I would be very grateful if someone could tell me how can i attach to few containers, so i could stop them all with ctrl + c (thats how the docker-compose up service1 service2 service3 without "-d" flag works)

Docker-compose volumes doesn't copy any files

I'm in Fedora 23 and i'm using docker-compose to build two containers: app and db.
I want to use that docker as my dev env, but have to execute docker-compose build and up every time i change the code isn't nice. So i was searching and tried the "volumes" option but my code doesn't get copied to docker.
When i run docker-build, a "RUN ls" command doesn't list the "app" folder or any files of it.
Obs.: in the root folder I have: docker-compose.yml, .gitignore, app (folder), db (folder)
Obs¹.: If I remove the volumes and working_dir options and instead I use a "COPY . /app" command inside the app/Dockerfile it works and my app is running, but I want it to sync my code.
Anyone know how to make it work?
My docker-compose file is:
version: '2'
services:
app:
build: ./app
ports:
- "3000:3000"
depends_on:
- db
environment:
- DATABASE_HOST=db
- DATABASE_USER=myuser
- DATABASE_PASSWORD=mypass
- DATABASE_NAME=dbusuarios
- PORT=3000
volumes:
- ./app:/app
working_dir: /app
db:
build: ./db
environment:
- MYSQL_ROOT_PASSWORD=123
- MYSQL_DATABASE=dbusuarios
- MYSQL_USER=myuser
- MYSQL_PASSWORD=mypass
Here you can see my app container Dockerfile:
https://gist.github.com/jradesenv/d3b5c09f2fcf3a41f392d665e4ca0fb9
Heres the output of the RUN ls command inside Dockerfile:
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
A volume is mounted in a container. The Dockerfile is used to create the image, and that image is used to make the container. What that means is a RUN ls inside your Dockerfile will show the filesystem before the volume is mounted. If you need these files to be part of the image for your build to complete, they shouldn't be in the volume and you'll need to copy them with the COPY command as you've described. If you simply want evidence that these files are mounted inside your running container, run a
docker exec $container_name ls -l /
Where $container_name will be something like ${folder_name}_app_1, which you'll see in a docker ps.
Two things, have you tried version: '3' version two seems to be outdated. Also try putting the working_dir into the Dockerfile rather than the docker-compose. Maybe it's not supported in version 2?
This is a recent docker-compose I have used with volumes and workdirs in the respective Dockerfiles:
version: '3'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- 3001:3001
volumes:
- ./frontend:/app
networks:
- frontend
backend:
build: .
ports:
- 3000:3000
volumes:
- .:/app
networks:
- frontend
- backend
depends_on:
- "mongo"
mongo:
image: mongo
volumes:
- ./data/db:/data/db
ports:
- 27017:27017
networks:
- backend
networks:
frontend:
backend:
You can extend or override docker compose configuration. Please follow for more info: https://docs.docker.com/compose/extends/
I had this same issue in Windows!
volumes:
- ./src/:/var/www/html
In windows ./src/ this syntax might not work in regular command prompt, so use powershell instead and then run docker-compose up -d.
it should work if it's a mounting issue.

Resources