I need to hide password of postgres in odoo container like in postgres container, when we create new container postgres we can pass env variable POSTGRES_PASSWORD_FILE, and the content of Dockerfile of postgres 9.6 contains this block of code:
#!/usr/bin/env bash
set -Eeo pipefail
# TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables)
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
How we can do the same code in odoo image?
You can try to add your whole odoo.conf as a secret, create your service and add that secret with the --secret file and point to the path /run/secrets/${MY_SECRET} on your entrypoint with the -c flag on the odoo command
Related
I am trying to find a "global" solution for injecting an SSH key into a container. I know that there are several solutions including docker build kit and so on...but I don't want to build an image and inject the SSH key. I want to inject the SSH key by using an existing image with docker compose.
I use the following docker compose file:
version: '3.1'
services:
server1:
image: XXXXXXX
container_name: server1
command: bash -c "/root/init.sh && python3 /root/my_python.py"
environment:
- MANAGED_HOST=mserver
volumes:
- ./init.sh:/root/init.sh
secrets:
- id_rsa
secrets:
id_rsa:
file: /home/user/.ssh/id_rsa
The init.sh is as follows:
#!/bin/bash
eval "$(ssh-agent -s)" > /dev/null
if [ ! -d "/root/.ssh/" ]; then
mkdir /root/.ssh
ssh-keyscan $MANAGED_HOST > /root/.ssh/known_hosts
fi
ssh-add -k /run/secrets/id_rsa
If I run docker compose with the parameter command
bash -c "/root/init.sh && python3 /root/my_python.py", then the SSH authentication to the appropriate remote host ($MANAGED_HOST) is not working.
An agent process is running:
root 8 1 0 12:50 ? 00:00:00 ssh-agent -s
known_hosts is OK:
root#c67655d87ced:~# cat /root/.ssh/known_hosts
BLABLABLA ssh-rsa AAAAB3BLABLABLA....
and the agent is running, but the private key is not added:
root#c67655d87ced:~# ssh-add -l
Could not open a connection to your authentication agent.
Now, if I log in the container (docker exec -it server1 /bin/bash) and run the commands from init.sh one by one from the command line, then the SSH authentication to the appropriate remote host ($MANAGED_HOST) is working?!?
Any idea, how I can get it working by using the docker compose?
It should be enough to cause the file $HOME/.ssh/id_rsa to exist with appropriate permissions; you don't need an ssh agent running.
#!/bin/sh
if ! [ -d "$HOME/.ssh" ]; then
mkdir "$HOME/.ssh"
fi
chmod 0700 "$HOME/.ssh"
if [ -n "$MANAGED_HOST" ]; then
ssh-keyscan "$MANAGED_HOST" >> "$HOME/.ssh/known_hosts"
fi
if [ -f /run/secrets/id_rsa ]; then
cp /run/secrets/id_rsa "$HOME/.ssh/id_rsa"
chmod 0400 "$HOME/.ssh/id_rsa"
fi
# exec "$#"
A typical pattern is to use the Dockerfile ENTRYPOINT to do first-time setup tasks like this. That will get passed the CMD as arguments, and the commented exec "$#" line at the end of the file runs that as a command. You'd set this up in your image's Dockerfile like:
FROM XXXXXX
...
# Script must be executable on the host, and must start with a
# #!/bin/sh "shebang" line
COPY init.sh /root
# MUST use JSON-array form
ENTRYPOINT ["/root/init.sh"]
# Can use any Dockerfile syntax
CMD ["python3", "/root/my_python.py"]
In your specific example, you're launching init.sh as a subprocess. The ssh-agent setup sets some environment variables, like $SSH_AUTH_SOCK, but when these run as a subprocess they don't get propagated back out to the host process. You can use the standard POSIX shell . builtin (the bash source builtin is equivalent, but non-standard) to cause those environment variables to be set in the context of the parent shell:
command: sh -c ". /root/init.sh && exec python3 /root/my_python.py"
The exec replaces the shell wrapper with the Python script, which you generally want. This will also wind up being the parent process of ssh-agent, which could potentially surprise your process if it happens to exit.
I have a jar file that contains the application.properties file.
can we configure the IP address and port number & username & password while running the docker image
Properties file location
App/bin/config/application.properties
Following are the application.properties
driverClassName = org.postgresql.Driver
url = jdbc:postgresql://localhost:5432/sakila
username = root
password = root
entrypoint is the secret.
You have two solutions:
design the image to receive these parameters thru environment variables, and let the ENTRYPOINT injects them inside App/bin/config/application.properties
design the image to listen to a directory. If this directory contains *.properties files, the ENTRYPOINT will collect these files and combine them into one file and append the content with App/bin/config/application.properties
Both solutions have the same Dockerfile
From java:x
COPY jar ...
COPY myentrypoint /
ENTRYPOINT ["bash", "/myentrypoint"]
But not the same ENTRYPOINT (myentrypoint)
solution A - entrypoint:
#!/bin/bash
# if the env var DB_URL is not empty
if [ ! -z "${DB_URL}" ]; then
echo "url=${DB_URL}" >> App/bin/config/application.properties
fi
# do the same for other props
#...
exec call-the-main-entry-point-here $#
To create a container from this solution :
docker run -it -e DB_URL=jdbc:postgresql://localhost:5432/sakila myimage
solution B - entrypoint:
#!/bin/bash
# if /etc/java/props.d/ is a directory
if [ -d "/etc/java/props.d/" ]; then
cat /etc/java/props.d/*.properties
awk '{print $0}' /etc/java/props.d/*.properties >> App/bin/config/application.properties
fi
#...
exec call-the-main-entry-point-here $#
To create a container from this solution :
docker run -it -v ./folder-has-props-files:/etc/java/props.d myimage
I am actually new to programming and Docker. I tried to rebuild the graphile/postgraphile:4.7.0 image to add DATABASE_URL_FILE environment variable support. This is what I do and the output.
Dockerfile
FROM node:alpine
LABEL description="Instant high-performance GraphQL API for your PostgreSQL database https://github.com/graphile/postgraphile"
# Install PostGraphile and PostGraphile connection filter plugin
RUN npm install -g postgraphile
RUN npm install -g postgraphile-plugin-connection-filter
EXPOSE 5000
# patch postgraphile:4.7.1; DATABASE_URL_FILE environment variable implementation.
RUN apk add bash
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgraphile", "-n", "0.0.0.0"]
docker-entrypoint.sh copied from postgres docker-entrypoint.sh
#!/usr/bin/env bash
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# Loads various settings that are used elsewhere in the script
# This should be called before any other functions
docker_setup_env() {
file_env 'DATABASE_URL'
}
output
$ docker-compose up postgraphile
Attaching to test_postgraphile_1
test_postgraphile_1 | exited with code 0
Sincerely,
kidfrom
Edit: Benjie (Postgraphile maintainer) helped me alot on this one. This should work as is.
Dockerfile
FROM node:alpine
LABEL description="Instant high-performance GraphQL API for your PostgreSQL database https://github.com/graphile/postgraphile"
# Install PostGraphile and PostGraphile connection filter plugin
RUN npm install -g postgraphile
RUN npm install -g postgraphile-plugin-connection-filter
EXPOSE 5000
# patch postgraphile:4.7.1; DATABASE_URL_FILE environment variable implementation.
RUN apk add bash
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgraphile", "-n", "0.0.0.0"]
docker-entrypoint.sh copied from postgres docker-entrypoint.sh
#!/usr/bin/env bash
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# Loads various settings that are used elsewhere in the script
# This should be called before any other functions
docker_setup_env() {
file_env 'DATABASE_URL'
}
# call the function
docker_setup_env
# call postgraphile
exec "$#"
Sincerely,
kidfrom
I have a Dockerfile that requires two environment variables:
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
I'm passing them from the host through my compose file using:
build:
# ...
args:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
My problem is that in some flows there is an IAM role set (and no env vars) and I don't want to use the environment variables. But even when they don't exist on the host they seem to be set to empty strings during the build process.
I've tried this:
run if [ -z "$AWS_ACCESS_KEY_ID" ]; then unset AWS_ACCESS_KEY_ID; fi
run if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then unset AWS_SECRET_ACCESS_KEY; fi
run env # see if set
But it doesn't work (the variables are still set even if not set in host env).
I'd welcome another solution on mixing env vars and IAM roles when building dockers.
Different run in Dockerfile not impact each other, to make your aims, suggest to combine them to one run, something likes follows, FYI:
run if [ -z "$AWS_ACCESS_KEY_ID" ]; then unset AWS_ACCESS_KEY_ID; fi && \
if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then unset AWS_SECRET_ACCESS_KEY; fi && \
env
Then, you will find no AWS_ACCESS_KEY_ID was set to empty value in env.
And, when try, suggest use docker-compose build --no-cache to test.
Finally, why you see empty value?
I made a experiment, seems if no ENV set in Dockerfile, meanwhile, no env for this variable set in HOST, the ARG in Dockerfile will automatically be changed to one ENV variable when docker build, as the ARG did not set a value, so it's empty.
I am running docker 17.03.0-ce on premise on an RHEL 7.3 64bit VM. I am pulling a weblogic 10.3.6 RHEL image and after that i modify weblogic domain config file which is required to run my application by passing the IP of the VM during docker run with the command "VM_IP=$(hostname -i)".So i have added sed command in the docker file along with server start script which replaces placeholder with VM IP in the config file. However, when the server starts, the config file seems to revert back to its original state, i.e. without the placeholder value getting replaced. I have observed that if i comment the server start script, the placeholder gets replaced with the proper. I tried executing the sed from a shell script which is the entry point and also tried running sed command from dockerfile.
Below is my docker file
FROM 192.168.1.1:5000/wcp_image:v6
WORKDIR /
USER root
ENV VM_IP=$vm_ip
RUN rm -rf
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config/config.xml
COPY config.xml
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config/
RUN chmod 777
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config/config.xml &&
chown -R wcpuser.wcpuser
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config/config.xml
COPY replace.sh /data/docker_setup
RUN chmod 777 /data/docker_setup/replace.sh
ENTRYPOINT ["/data/docker_setup/replace.sh"]
CMD ["$VM_IP"]
And below is the replace.sh shell script
#!/bin/bash
cd /data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config
sed -i -r "s/VM_IP/$VM_IP/g"
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/config/config.xml
/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN/bin/startWebLogic.sh
Please let me know. Thanks in advance.
Update
Below is the startWeblogic.sh script from the container
#!/bin/sh
# WARNING: This file is created by the Configuration Wizard.
# Any changes to this script may be lost when adding extensions to this configuration.
# --- Start Functions ---
stopAll()
{
# We separate the stop commands into a function so we are able to use the trap command in Unix (calling a function) to stop these services
if [ "X${ALREADY_STOPPED}" != "X" ] ; then
exit
fi
# STOP DERBY (only if we started it)
if [ "${DERBY_FLAG}" = "true" ] ; then
echo "Stopping Derby server..."
${WL_HOME}/common/derby/bin/stopNetworkServer.sh >"${DOMAIN_HOME}/derbyShutdown.log" 2>&1
echo "Derby server stopped."
fi
ALREADY_STOPPED="true"
}
classCaching()
{
echo "Class caching enabled..."
JAVA_OPTIONS="${JAVA_OPTIONS} -Dlaunch.main.class=${SERVER_CLASS} -Dlaunch.class.path="${CLASSPATH}" -Dlaunch.complete=weblogic.store.internal.LockManagerImpl -cp ${WL_HOME}/server/lib/pcl2.jar"
export JAVA_OPTIONS
SERVER_CLASS="com.oracle.classloader.launch.Launcher"
}
# --- End Functions ---
# *************************************************************************
# This script is used to start WebLogic Server for this domain.
#
# To create your own start script for your domain, you can initialize the
# environment by calling #USERDOMAINHOME/setDomainEnv.
#
# setDomainEnv initializes or calls commEnv to initialize the following variables:
#
# BEA_HOME - The BEA home directory of your WebLogic installation.
# JAVA_HOME - Location of the version of Java used to start WebLogic
# Server.
# JAVA_VENDOR - Vendor of the JVM (i.e. BEA, HP, IBM, Sun, etc.)
# PATH - JDK and WebLogic directories are added to system path.
# WEBLOGIC_CLASSPATH
# - Classpath needed to start WebLogic Server.
# PATCH_CLASSPATH - Classpath used for patches
# PATCH_LIBPATH - Library path used for patches
# PATCH_PATH - Path used for patches
# WEBLOGIC_EXTENSION_DIRS - Extension dirs for WebLogic classpath patch
# JAVA_VM - The java arg specifying the VM to run. (i.e.
# - server, -hotspot, etc.)
# USER_MEM_ARGS - The variable to override the standard memory arguments
# passed to java.
# PRODUCTION_MODE - The variable that determines whether Weblogic Server is started in production mode.
# DERBY_HOME - Derby home directory.
# DERBY_CLASSPATH
# - Classpath needed to start Derby.
#
# Other variables used in this script include:
# SERVER_NAME - Name of the weblogic server.
# JAVA_OPTIONS - Java command-line options for running the server. (These
# will be tagged on to the end of the JAVA_VM and
# MEM_ARGS)
# CLASS_CACHE - Enable class caching of system classpath.
#
# For additional information, refer to "Managing Server Startup and Shutdown for Oracle WebLogic Server"
# (http://download.oracle.com/docs/cd/E17904_01/web.1111/e13708/overview.htm).
# *************************************************************************
umask 037
# Call setDomainEnv here.
DOMAIN_HOME="/data/Oracle/Middleware/user_projects/domains/WCP_DOMAIN"
. ${DOMAIN_HOME}/bin/setDomainEnv.sh $*
SAVE_JAVA_OPTIONS="${JAVA_OPTIONS}"
SAVE_CLASSPATH="${CLASSPATH}"
# Start Derby
DERBY_DEBUG_LEVEL="0"
if [ "${DERBY_FLAG}" = "true" ] ; then
${WL_HOME}/common/derby/bin/startNetworkServer.sh >"${DOMAIN_HOME}/derby.log" 2>&1
fi
JAVA_OPTIONS="${SAVE_JAVA_OPTIONS}"
SAVE_JAVA_OPTIONS=""
CLASSPATH="${SAVE_CLASSPATH}"
SAVE_CLASSPATH=""
trap 'stopAll' 1 2 3 15
if [ "${PRODUCTION_MODE}" = "true" ] ; then
WLS_DISPLAY_MODE="Production"
else
WLS_DISPLAY_MODE="Development"
fi
if [ "${WLS_USER}" != "" ] ; then
JAVA_OPTIONS="${JAVA_OPTIONS} -Dweblogic.management.username=${WLS_USER}"
fi
if [ "${WLS_PW}" != "" ] ; then
JAVA_OPTIONS="${JAVA_OPTIONS} -Dweblogic.management.password=${WLS_PW}"
fi
if [ "${MEDREC_WEBLOGIC_CLASSPATH}" != "" ] ; then
if [ "${CLASSPATH}" != "" ] ; then
CLASSPATH="${CLASSPATH}${CLASSPATHSEP}${MEDREC_WEBLOGIC_CLASSPATH}"
else
CLASSPATH="${MEDREC_WEBLOGIC_CLASSPATH}"
fi
fi
echo "."
echo "."
echo "JAVA Memory arguments: ${MEM_ARGS}"
echo "."
echo "WLS Start Mode=${WLS_DISPLAY_MODE}"
echo "."
echo "CLASSPATH=${CLASSPATH}"
echo "."
echo "PATH=${PATH}"
echo "."
echo "***************************************************"
echo "* To start WebLogic Server, use a username and *"
echo "* password assigned to an admin-level user. For *"
echo "* server administration, use the WebLogic Server *"
echo "* console at http://hostname:port/console *"
echo "***************************************************"
# CLASS CACHING
if [ "${CLASS_CACHE}" = "true" ] ; then
classCaching
fi
# START WEBLOGIC
echo "starting weblogic with Java version:"
${JAVA_HOME}/bin/java ${JAVA_VM} -version
if [ "${WLS_REDIRECT_LOG}" = "" ] ; then
echo "Starting WLS with line:"
echo "${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -Dweblogic.Name=${SERVER_NAME} -Djava.security.policy=${WL_HOME}/server/lib/weblogic.policy ${JAVA_OPTIONS} ${PROXY_SETTINGS} ${SERVER_CLASS}"
${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -Dweblogic.Name=${SERVER_NAME} -Djava.security.policy=${WL_HOME}/server/lib/weblogic.policy ${JAVA_OPTIONS} ${PROXY_SETTINGS} ${SERVER_CLASS}
else
echo "Redirecting output from WLS window to ${WLS_REDIRECT_LOG}"
${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -Dweblogic.Name=${SERVER_NAME} -Djava.security.policy=${WL_HOME}/server/lib/weblogic.policy ${JAVA_OPTIONS} ${PROXY_SETTINGS} ${SERVER_CLASS} >"${WLS_REDIRECT_LOG}" 2>&1
fi
stopAll
popd
# Exit this script only if we have been told to exit.
if [ "${doExitFlag}" = "true" ] ; then
exit
fi