
Estoy intentando crear un destino Makefile que primero verifica si mi contenedor Docker existe. Si existe, quiero emitir el comando Docker Container Restart; de lo contrario, quiero emitir el comando Docker Run para crear e iniciar el contenedor.
He codificado lo siguiente pero aparece el error que se muestra a continuación. El resultado = 1 es correcto ya que tengo un contenedor en ejecución. Quité el contenedor y probé que el resultado se convierte en 0, lo cual también es correcto. El problema parece surgir cuando intento utilizar el resultado en la ifeq
declaración. ¿Alguien puede aconsejarme qué estoy haciendo mal? (Comenté temporalmente los comandos de la ventana acoplable y los reemplacé con echo true/false justo mientras estoy depurando).
start_docker_myapp:
result = $(shell (docker ps -a | grep myapp ) | wc -l )
ifeq (${result}, 1)
@echo 'true'
# docker restart ${IMAGE}
else
@echo 'false'
# docker run -v ${DIR}/var/log/docker:/var/log/myapp -p 1812:1812/udp -p 1813:1813/udp --detach --name ${IMAGE} $(REGISTRY)/$(IMAGE):$(TAG)
endif
Salida desde la terminal
$ make start_docker_myapp result = 1 make: result: No such file or directory make: *** [start_docker_myapp] Error 1 $
Respuesta1
Hay una serie de problemas con su Makefile (más allá de la cuestión de si un Makefile es la solución adecuada):
- las directivas condicionales no son parte de una receta, por lo que no deben comenzar con una pestaña;
- las directivas condicionales se evalúan a medida que se lee el Makefile, por lo que las variables deben asignarse previamente y no pueden ser específicas de un objetivo;
docker ps -a
devuelve información sobre todos los contenedores conocidos, incluidos los contenedores que no están en funcionamiento;- Los objetivos falsos deben declararse como tales.
Las siguientes obras:
result = $(shell docker ps -f name=myapp -q | wc -l)
start_docker_myapp:
ifeq ($(strip $(result)),1)
@echo true
else
@echo false
endif
.PHONY: start_docker_myapp
Respuesta2
Para establecer un valor de variable dentro de un objetivo, debe usar la eval
sintaxis:
start_docker_myapp:
$(eval result = $(shell (docker ps -a | grep myapp ) | wc -l ))
@echo "result is " result
endif
Alternativamente, puedes evaluar esta variable fuera de una regla:
result = $(shell (docker ps -a | grep myapp ) | wc -l )
start_docker_myapp:
@echo "result is " result
endif
Respuesta3
En lugar de implementar una combinación de código de script de shell y crear variables, sugiero implementar esto como un script de shell puro integrado en el archivo Makefile
.
En lugar de verificar la salida de grep
with wc
y comparar el número, simplemente puede verificar grep
el código de salida de .
# don't forget to declare start_docker_myapp as a phony target
.PHONY: start_docker_myapp
# Assuming you intended to use Make variables everywhere, I changed all ${VAR} to $(VAR).
# If your grep supports option -q you can use this instead of redirection to /dev/null.
start_docker_myapp:
if docker ps -a | grep myapp >/dev/null; \
then \
echo 'true'; \
# docker restart $(IMAGE); \
else \
echo 'false'; \
# docker run -v $(DIR)/var/log/docker:/var/log/myapp -p 1812:1812/udp -p 1813:1813/udp --detach --name $(IMAGE) $(REGISTRY)/$(IMAGE):$(TAG); \
fi
O con operadores booleanos en lugar deif...then...
.PHONY: start_docker_myapp
start_docker_myapp:
docker ps -a | grep myapp >/dev/null && docker restart $(IMAGE) || docker run -v $(DIR)/var/log/docker:/var/log/myapp -p 1812:1812/udp -p 1813:1813/udp --detach --name $(IMAGE) $(REGISTRY)/$(IMAGE):$(TAG)